diff --git a/public/architecture.html b/public/architecture.html index 8253ad60..ad79de5b 100644 --- a/public/architecture.html +++ b/public/architecture.html @@ -312,6 +312,44 @@ + +
+
+
+

Explore the Architecture Interactively

+

+ Click any service node to see detailed information about how it enforces governance boundaries. +

+
+ +
+ +
+ + + Tractatus Architecture Diagram + +
+ +
+

+ + + + Tip: Click any colored circle to explore that governance service +

+
+ + +
+
+
+
@@ -466,6 +504,9 @@ + + + diff --git a/public/images/architecture-diagram-interactive.svg b/public/images/architecture-diagram-interactive.svg new file mode 100644 index 00000000..c18e84e3 --- /dev/null +++ b/public/images/architecture-diagram-interactive.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + B + BoundaryEnforcer - Click for details + + + + + + I + InstructionPersistenceClassifier - Click for details + + + + + + V + CrossReferenceValidator - Click for details + + + + + + P + ContextPressureMonitor - Click for details + + + + + + M + MetacognitiveVerifier - Click for details + + + + + + D + PluralisticDeliberationOrchestrator - Click for details + + + + + + + + T + Tractatus + + + + diff --git a/public/js/components/interactive-diagram.js b/public/js/components/interactive-diagram.js new file mode 100644 index 00000000..b5fb9a8c --- /dev/null +++ b/public/js/components/interactive-diagram.js @@ -0,0 +1,352 @@ +/** + * Interactive Architecture Diagram Component + * Tractatus Framework - Phase 3: Interactive Architecture Diagram + * + * Handles click/hover interactions on the hexagonal service diagram + * Shows service details in a side panel + */ + +class InteractiveDiagram { + constructor() { + this.serviceData = { + boundary: { + name: 'BoundaryEnforcer', + shortName: 'Boundary', + color: '#10b981', + icon: '🔒', + description: 'Blocks AI from making values decisions (privacy, ethics, strategic direction). Requires human approval.', + details: [ + 'Enforces Tractatus 12.1-12.7 boundaries', + 'Values decisions architecturally require humans', + 'Prevents AI autonomous decision-making on ethical questions', + 'External enforcement - harder to bypass via prompting' + ], + promise: 'Values boundaries enforced externally—harder to manipulate through prompting.' + }, + instruction: { + name: 'InstructionPersistenceClassifier', + shortName: 'Instruction', + color: '#6366f1', + icon: '📋', + description: 'Stores instructions externally with persistence levels (HIGH/MEDIUM/LOW). Aims to reduce directive fade.', + details: [ + 'Quadrant-based classification (STR/OPS/TAC/SYS/STO)', + 'Time-persistence metadata tagging', + 'Temporal horizon modeling (STRATEGIC, OPERATIONAL, TACTICAL)', + 'External storage independent of AI runtime' + ], + promise: 'Instructions stored outside AI—more resistant to context manipulation.' + }, + validator: { + name: 'CrossReferenceValidator', + shortName: 'Validator', + color: '#8b5cf6', + icon: '✓', + description: 'Validates AI actions against instruction history. Aims to prevent pattern bias overriding explicit directives.', + details: [ + 'Cross-references AI claims with external instruction history', + 'Detects pattern-based overrides of explicit user directives', + 'Independent verification layer', + 'Helps prevent instruction drift' + ], + promise: 'Independent verification—AI claims checked against external source.' + }, + pressure: { + name: 'ContextPressureMonitor', + shortName: 'Pressure', + color: '#f59e0b', + icon: '⚡', + description: 'Monitors AI performance degradation. Escalates when context pressure threatens quality.', + details: [ + 'Tracks token usage, complexity, error rates', + 'Detects degraded operating conditions', + 'Adjusts verification requirements under pressure', + 'Objective metrics for quality monitoring' + ], + promise: 'Objective metrics may detect manipulation attempts early.' + }, + metacognitive: { + name: 'MetacognitiveVerifier', + shortName: 'Metacognitive', + color: '#ec4899', + icon: '💡', + description: 'Requires AI to pause and verify complex operations before execution. Structural safety check.', + details: [ + 'AI self-checks alignment, coherence, safety before execution', + 'Structural pause-and-verify gates', + 'Selective verification (not constant)', + 'Architectural enforcement of reflection steps' + ], + promise: 'Architectural gates aim to enforce verification steps.' + }, + deliberation: { + name: 'PluralisticDeliberationOrchestrator', + shortName: 'Deliberation', + color: '#14b8a6', + icon: '👥', + description: 'Facilitates multi-stakeholder deliberation for values conflicts where no single "correct" answer exists.', + details: [ + 'Non-hierarchical coordination for values conflicts', + 'Stakeholder perspective representation', + 'Consensus-building for ethical trade-offs', + 'Addresses values pluralism in AI safety' + ], + promise: 'Facilitates deliberation across stakeholder perspectives for values conflicts.' + } + }; + + this.activeService = null; + this.init(); + } + + init() { + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => this.setup()); + } else { + this.setup(); + } + + console.log('[InteractiveDiagram] Initialized'); + } + + setup() { + const svg = document.getElementById('interactive-arch-diagram'); + if (!svg) { + console.warn('[InteractiveDiagram] SVG diagram not found'); + return; + } + + const nodes = svg.querySelectorAll('.service-node'); + console.log(\`[InteractiveDiagram] Found \${nodes.length} service nodes\`); + + nodes.forEach(node => { + const serviceId = node.getAttribute('data-service'); + + node.addEventListener('click', (e) => { + e.preventDefault(); + this.showServiceDetails(serviceId); + }); + + node.addEventListener('mouseenter', () => { + this.highlightService(serviceId); + }); + + node.addEventListener('mouseleave', () => { + this.unhighlightService(serviceId); + }); + }); + + this.addKeyboardNavigation(nodes); + } + + highlightService(serviceId) { + const svg = document.getElementById('interactive-arch-diagram'); + if (!svg) return; + + const connectionLine = svg.querySelector(\`#conn-\${serviceId}\`); + if (connectionLine) { + connectionLine.classList.add('active'); + } + + const node = svg.querySelector(\`#node-\${serviceId}\`); + if (node) { + node.classList.add('hover'); + } + } + + unhighlightService(serviceId) { + const svg = document.getElementById('interactive-arch-diagram'); + if (!svg) return; + + if (this.activeService === serviceId) return; + + const connectionLine = svg.querySelector(\`#conn-\${serviceId}\`); + if (connectionLine) { + connectionLine.classList.remove('active'); + } + + const node = svg.querySelector(\`#node-\${serviceId}\`); + if (node) { + node.classList.remove('hover'); + } + } + + showServiceDetails(serviceId) { + const service = this.serviceData[serviceId]; + if (!service) { + console.error('[InteractiveDiagram] Service not found:', serviceId); + return; + } + + this.activeService = serviceId; + + const svg = document.getElementById('interactive-arch-diagram'); + if (svg) { + svg.querySelectorAll('.service-node').forEach(n => n.classList.remove('active')); + svg.querySelectorAll('.connection-line').forEach(l => l.classList.remove('active')); + + const node = svg.querySelector(\`#node-\${serviceId}\`); + if (node) { + node.classList.add('active'); + } + + const connectionLine = svg.querySelector(\`#conn-\${serviceId}\`); + if (connectionLine) { + connectionLine.classList.add('active'); + } + } + + this.renderServicePanel(service); + + console.log('[InteractiveDiagram] Showing details for:', service.name); + } + + renderServicePanel(service) { + let panel = document.getElementById('service-detail-panel'); + + if (!panel) { + panel = document.createElement('div'); + panel.id = 'service-detail-panel'; + panel.className = 'bg-white rounded-xl shadow-2xl p-6 border-2'; + panel.style.borderColor = service.color; + + const container = document.querySelector('#diagram-container'); + if (container) { + container.appendChild(panel); + } else { + console.error('[InteractiveDiagram] Diagram container not found'); + return; + } + } else { + panel.style.borderColor = service.color; + } + + const html = \` +
+
+
+ \${service.icon} +
+
+

\${service.name}

+ \${service.shortName} +
+
+ +
+ +

\${service.description}

+ +
+

Key Features

+
    + \${service.details.map(detail => \` +
  • + + + + \${detail} +
  • + \`).join('')} +
+
+ +
+ Early Promise: + \${service.promise} +
+ \`; + + panel.innerHTML = html; + + // Apply styles via JavaScript (CSP-compliant) + const iconBox = panel.querySelector('.service-icon-box'); + if (iconBox) { + const color = iconBox.getAttribute('data-color'); + iconBox.style.background = \`linear-gradient(135deg, \${color} 0%, \${color}dd 100%)\`; + } + + // Style all check icons + const checkIcons = panel.querySelectorAll('.service-check-icon'); + checkIcons.forEach(icon => { + const color = icon.getAttribute('data-color'); + icon.style.color = color; + }); + + // Style promise badge + const promiseBadge = panel.querySelector('.service-promise-badge'); + if (promiseBadge) { + const color = promiseBadge.getAttribute('data-color'); + promiseBadge.style.backgroundColor = color; + } + + // Style promise text + const promiseText = panel.querySelector('.service-promise-text'); + if (promiseText) { + const color = promiseText.getAttribute('data-color'); + promiseText.style.color = color; + } + + // Add close button event listener (CSP-compliant) + const closeBtn = panel.querySelector('#close-panel-btn'); + if (closeBtn) { + closeBtn.addEventListener('click', () => this.closePanel()); + } + + panel.style.opacity = '0'; + panel.style.transform = 'translateY(20px)'; + panel.style.transition = 'opacity 0.3s ease, transform 0.3s ease'; + + setTimeout(() => { + panel.style.opacity = '1'; + panel.style.transform = 'translateY(0)'; + }, 10); + } + + closePanel() { + const panel = document.getElementById('service-detail-panel'); + if (panel) { + panel.style.opacity = '0'; + panel.style.transform = 'translateY(20px)'; + + setTimeout(() => { + panel.remove(); + }, 300); + } + + const svg = document.getElementById('interactive-arch-diagram'); + if (svg) { + svg.querySelectorAll('.service-node').forEach(n => n.classList.remove('active')); + svg.querySelectorAll('.connection-line').forEach(l => l.classList.remove('active')); + } + + this.activeService = null; + } + + addKeyboardNavigation(nodes) { + nodes.forEach((node, index) => { + node.setAttribute('tabindex', '0'); + node.setAttribute('role', 'button'); + + node.addEventListener('keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + const serviceId = node.getAttribute('data-service'); + this.showServiceDetails(serviceId); + } + }); + }); + } +} + +if (typeof window !== 'undefined') { + window.interactiveDiagram = new InteractiveDiagram(); +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = InteractiveDiagram; +}