diff --git a/public/implementer.html b/public/implementer.html index 57c48e96..7f6b43c0 100644 --- a/public/implementer.html +++ b/public/implementer.html @@ -27,9 +27,9 @@ - - - + + + + + + + +
+
+
⚑
+

Agent Lightning Integration

+

Combining Microsoft's reinforcement learning optimization with Tractatus governance through architectural separation

+
+
+

Overview

+

+ Agent Lightning (Microsoft) uses reinforcement learning to optimize agentic AI systems through continuous training on human feedback. +

+
+

+ Tractatus addresses governance persistence through architectural separation: governance services run independently of the optimization layer. +

+
+
+
+

Join the Community

+
+
+

Tractatus Discord

+

Governance-focused discussions

+ Join Tractatus Server β†’ +
+
+

Agent Lightning Discord

+

Technical implementation help

+ Join Agent Lightning Server β†’ +
+
+
+
+ + + + diff --git a/public/js/components/feedback.js b/public/js/components/feedback.js new file mode 100644 index 00000000..6ca3ff55 --- /dev/null +++ b/public/js/components/feedback.js @@ -0,0 +1,605 @@ +/** + * Tractatus Framework - Governed Feedback Component + * Demonstrates Agent Lightning + Tractatus governance in action + * + * Features: + * - Floating Action Button (FAB) for quick access + * - Modal dialog for feedback submission + * - Mobile-optimized bottom sheet + * - Real-time governance pathway classification + * - Integration with BoundaryEnforcer, PluralisticDeliberator, CrossReferenceValidator + */ + +class TractausFeedback { + constructor() { + this.isOpen = false; + this.isMobile = window.matchMedia('(max-width: 768px)').matches; + this.selectedType = null; + this.csrfToken = null; + + this.init(); + } + + async init() { + // Get CSRF token + await this.fetchCsrfToken(); + + // Render components + this.renderFAB(); + this.renderModal(); + + // Attach event listeners + this.attachEventListeners(); + + // Listen for window resize + window.addEventListener('resize', () => { + this.isMobile = window.matchMedia('(max-width: 768px)').matches; + }); + + // Listen for external open feedback requests (from navbar, etc.) + window.addEventListener('openFeedbackModal', () => { + this.openModal(); + }); + } + + async fetchCsrfToken() { + try { + const response = await fetch('/api/csrf-token'); + const data = await response.json(); + this.csrfToken = data.csrfToken; + } catch (error) { + console.error('[Feedback] Failed to fetch CSRF token:', error); + } + } + + /** + * Render Floating Action Button (FAB) + * Omnipresent on all pages for quick feedback access + */ + renderFAB() { + const fabHTML = ` + + `; + + document.body.insertAdjacentHTML('beforeend', fabHTML); + } + + /** + * Render Feedback Modal/Bottom Sheet + * Adapts to mobile (bottom sheet) vs desktop (modal) + */ + renderModal() { + const modalHTML = ` + + + `; + + document.body.insertAdjacentHTML('beforeend', modalHTML); + } + + /** + * Attach all event listeners + */ + attachEventListeners() { + // FAB click - open modal + const fab = document.getElementById('feedback-fab'); + if (fab) { + fab.addEventListener('click', () => this.openModal()); + } + + // Close buttons + const closeBtn = document.getElementById('feedback-close-btn'); + const backdrop = document.getElementById('feedback-backdrop'); + if (closeBtn) closeBtn.addEventListener('click', () => this.closeModal()); + if (backdrop) backdrop.addEventListener('click', () => this.closeModal()); + + // Type selection buttons + const typeButtons = document.querySelectorAll('.feedback-type-btn'); + typeButtons.forEach(btn => { + btn.addEventListener('click', () => { + this.selectedType = btn.getAttribute('data-type'); + this.showStep2(); + }); + }); + + // Back button + const backBtn = document.getElementById('feedback-back-btn'); + if (backBtn) { + backBtn.addEventListener('click', () => this.showStep1()); + } + + // Form submission + const form = document.getElementById('feedback-form'); + if (form) { + form.addEventListener('submit', (e) => this.handleSubmit(e)); + } + + // Done button + const doneBtn = document.getElementById('feedback-done-btn'); + if (doneBtn) { + doneBtn.addEventListener('click', () => this.closeModal()); + } + } + + /** + * Open feedback modal + */ + openModal() { + this.isOpen = true; + const modal = document.getElementById('feedback-modal'); + const panel = document.getElementById('feedback-panel'); + + modal.classList.remove('hidden'); + + // Animate in + setTimeout(() => { + panel.classList.remove('translate-y-full'); + panel.classList.add('translate-y-0'); + }, 10); + + // Prevent body scroll + document.body.style.overflow = 'hidden'; + + // Reset to step 1 + this.showStep1(); + } + + /** + * Close feedback modal + */ + closeModal() { + this.isOpen = false; + const modal = document.getElementById('feedback-modal'); + const panel = document.getElementById('feedback-panel'); + + // Animate out + panel.classList.remove('translate-y-0'); + panel.classList.add('translate-y-full'); + + setTimeout(() => { + modal.classList.add('hidden'); + }, 300); + + // Restore body scroll + document.body.style.overflow = ''; + + // Reset form + this.resetForm(); + } + + /** + * Show step 1 (type selection) + */ + showStep1() { + document.getElementById('feedback-step-1').classList.remove('hidden'); + document.getElementById('feedback-step-2').classList.add('hidden'); + document.getElementById('feedback-step-3').classList.add('hidden'); + } + + /** + * Show step 2 (feedback form) + */ + showStep2() { + document.getElementById('feedback-step-1').classList.add('hidden'); + document.getElementById('feedback-step-2').classList.remove('hidden'); + document.getElementById('feedback-step-3').classList.add('hidden'); + + // Update pathway indicator based on type + this.updatePathwayIndicator(); + } + + /** + * Show step 3 (confirmation) + */ + showStep3(data) { + document.getElementById('feedback-step-1').classList.add('hidden'); + document.getElementById('feedback-step-2').classList.add('hidden'); + document.getElementById('feedback-step-3').classList.remove('hidden'); + + // Display confirmation message + const confirmationMessage = document.getElementById('confirmation-message'); + confirmationMessage.textContent = data.message; + + // Display tracking ID + const trackingId = document.getElementById('tracking-id'); + trackingId.textContent = data.feedbackId; + + // Display governance summary + this.displayGovernanceSummary(data); + } + + /** + * Update pathway indicator based on selected type + */ + updatePathwayIndicator() { + const indicator = document.getElementById('pathway-indicator'); + const constraintsList = document.getElementById('constraints-list'); + + const pathwayInfo = { + technical_question: { + pathway: 'Autonomous', + color: 'blue', + icon: 'πŸ€–', + description: 'AI will respond autonomously with technical information', + constraints: ['cite_documentation', 'no_financial_commitments', 'no_legal_advice', 'accurate_only'] + }, + bug: { + pathway: 'Autonomous', + color: 'blue', + icon: 'πŸ€–', + description: 'AI will respond autonomously with troubleshooting guidance', + constraints: ['cite_documentation', 'no_financial_commitments', 'accurate_only'] + }, + general: { + pathway: 'Autonomous', + color: 'blue', + icon: 'πŸ€–', + description: 'AI will respond autonomously with general information', + constraints: ['cite_documentation', 'no_financial_commitments', 'no_legal_advice', 'stay_on_topic'] + }, + feature: { + pathway: 'Deliberation', + color: 'amber', + icon: 'βš–οΈ', + description: 'Requires multi-stakeholder deliberation before response', + constraints: ['align_with_roadmap', 'assess_scope', 'community_benefit'] + }, + research: { + pathway: 'Deliberation', + color: 'amber', + icon: 'βš–οΈ', + description: 'Requires stakeholder consultation (maintainer, research lead, community)', + constraints: ['check_availability', 'align_with_research_gaps', 'assess_mutual_benefit'] + }, + commercial: { + pathway: 'Human Mandatory', + color: 'red', + icon: 'πŸ‘€', + description: 'Requires personal human review and response', + constraints: ['no_financial_commitments', 'no_pricing_discussion', 'refer_to_human'] + } + }; + + const info = pathwayInfo[this.selectedType]; + + indicator.className = `mb-6 p-4 rounded-lg border-2 border-${info.color}-200 bg-${info.color}-50`; + indicator.innerHTML = ` +
+ ${info.icon} +
+

Pathway: ${info.pathway}

+

${info.description}

+
+
+ `; + + // Display constraints + constraintsList.innerHTML = info.constraints.map(c => ` +
  • + + + + ${this.formatConstraint(c)} +
  • + `).join(''); + } + + /** + * Format constraint for display + */ + formatConstraint(constraint) { + const labels = { + cite_documentation: 'Must cite documentation', + no_financial_commitments: 'No financial commitments', + no_legal_advice: 'No legal advice', + accurate_only: 'Factually accurate only', + helpful_tone: 'Helpful, respectful tone', + stay_on_topic: 'Stay on topic', + align_with_roadmap: 'Align with roadmap', + assess_scope: 'Assess feasibility', + community_benefit: 'Community benefit assessment', + check_availability: 'Check maintainer availability', + align_with_research_gaps: 'Align with research priorities', + assess_mutual_benefit: 'Mutual benefit assessment', + no_pricing_discussion: 'No pricing discussion', + refer_to_human: 'Escalate to human' + }; + + return labels[constraint] || constraint; + } + + /** + * Handle form submission + */ + async handleSubmit(e) { + e.preventDefault(); + + const submitBtn = document.getElementById('feedback-submit-btn'); + submitBtn.disabled = true; + submitBtn.textContent = 'Submitting...'; + + try { + const formData = { + type: this.selectedType, + content: document.getElementById('feedback-content').value, + name: document.getElementById('feedback-name').value || null, + email: document.getElementById('feedback-email').value || null + }; + + const response = await fetch('/api/feedback/submit', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-Token': this.csrfToken + }, + credentials: 'include', + body: JSON.stringify(formData) + }); + + const data = await response.json(); + + if (data.success) { + this.showStep3(data); + } else { + alert('Error: ' + (data.message || 'Failed to submit feedback')); + submitBtn.disabled = false; + submitBtn.textContent = 'Submit Feedback'; + } + } catch (error) { + console.error('[Feedback] Submission error:', error); + alert('An error occurred. Please try again.'); + submitBtn.disabled = false; + submitBtn.textContent = 'Submit Feedback'; + } + } + + /** + * Display governance summary after submission + */ + displayGovernanceSummary(data) { + const summary = document.getElementById('governance-summary'); + + const pathwayIcons = { + autonomous: 'πŸ€–', + deliberation: 'βš–οΈ', + human_mandatory: 'πŸ‘€' + }; + + summary.innerHTML = ` +
    +

    Governance Summary

    +
    +
    + ${pathwayIcons[data.pathway]} + Pathway: ${data.pathway.replace('_', ' ')} +
    +
    Classification: BoundaryEnforcer approved
    +
    Tracking: ${data.feedbackId}
    + ${data.trackingUrl ? `` : ''} +
    +
    + `; + } + + /** + * Reset form to initial state + */ + resetForm() { + this.selectedType = null; + document.getElementById('feedback-form').reset(); + this.showStep1(); + } +} + +// Auto-initialize when DOM is ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => new TractausFeedback()); +} else { + new TractausFeedback(); +} diff --git a/public/leader.html b/public/leader.html index 6b8fcf04..df2e5b1a 100644 --- a/public/leader.html +++ b/public/leader.html @@ -35,9 +35,9 @@ - - - + + +