diff --git a/.continuum/genome/SETUP-COMPLETE.md b/.continuum/genome/SETUP-COMPLETE.md index b3527a7e2..9e0508da6 100644 --- a/.continuum/genome/SETUP-COMPLETE.md +++ b/.continuum/genome/SETUP-COMPLETE.md @@ -30,7 +30,7 @@ ### 2. TypeScript Integration **Modified Files:** -- `src/debug/jtag/system/genome/fine-tuning/server/adapters/UnslothLoRAAdapter.ts` +- `src/system/genome/fine-tuning/server/adapters/UnslothLoRAAdapter.ts` - `supportsFineTuning()`: Checks if environment bootstrapped - `executeUnslothTraining()`: Uses wrapper script (auto-activates conda) - Clear error messages if environment missing @@ -299,7 +299,7 @@ If Unsloth import fails, training falls back to standard PyTorch (slower but wor .gitignore # MODIFIED - Added genome paths -src/debug/jtag/system/genome/fine-tuning/server/adapters/ +src/system/genome/fine-tuning/server/adapters/ └── UnslothLoRAAdapter.ts # MODIFIED - Uses wrapper script ``` @@ -319,7 +319,7 @@ src/debug/jtag/system/genome/fine-tuning/server/adapters/ ## Questions? **Setup issues:** See `.continuum/genome/python/README.md` -**Architecture questions:** See `src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md` +**Architecture questions:** See `src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md` **Training errors:** Run test script first to verify environment **Philosophy:** "Test the shit out of it" - Every piece is validated before integration. diff --git a/.continuum/genome/python/README.md b/.continuum/genome/python/README.md index 931cead2f..0b416b1d1 100644 --- a/.continuum/genome/python/README.md +++ b/.continuum/genome/python/README.md @@ -101,7 +101,7 @@ python3 -c "import unsloth; print(unsloth.__version__)" ```bash .continuum/genome/python/train-wrapper.sh \ - src/debug/jtag/system/genome/fine-tuning/server/adapters/scripts/peft-train.py \ + src/system/genome/fine-tuning/server/adapters/scripts/peft-train.py \ --config config.json \ --output output/ ``` @@ -245,5 +245,5 @@ If training fails with unclear errors: 4. Check logs in temporary test directory For architecture questions, see: -- `src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md` -- `src/debug/jtag/system/user/server/modules/LORA-GENOME-PAGING.md` +- `src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md` +- `src/system/user/server/modules/LORA-GENOME-PAGING.md` diff --git a/.continuum/genome/python/test-training.sh b/.continuum/genome/python/test-training.sh index 3c83b3e02..545daf4a7 100644 --- a/.continuum/genome/python/test-training.sh +++ b/.continuum/genome/python/test-training.sh @@ -75,7 +75,7 @@ echo "" mkdir -p "$TEST_DIR/output" if "$SCRIPT_DIR/train-wrapper.sh" \ - "$(dirname "$SCRIPT_DIR")/../../src/debug/jtag/system/genome/fine-tuning/server/adapters/scripts/unsloth-train.py" \ + "$(dirname "$SCRIPT_DIR")/../../src/system/genome/fine-tuning/server/adapters/scripts/unsloth-train.py" \ --config "$TEST_DIR/config.json" \ --output "$TEST_DIR/output"; then diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 7ded641e3..000000000 --- a/.eslintignore +++ /dev/null @@ -1,17 +0,0 @@ -# Dependency directories -node_modules/ -dist/ - -# Build outputs -build/ -coverage/ - -# Configuration files -*.config.js -jest.config.js - -# Examples -examples/ - -# Generated files -*.d.ts \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 2302ee91c..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - root: true, - parser: '@typescript-eslint/parser', - plugins: [ - '@typescript-eslint', - ], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - ], - env: { - node: true, - jest: true, - }, - rules: { - // Override default rules here - '@typescript-eslint/no-explicit-any': 'warn', - '@typescript-eslint/no-unused-vars': ['warn', { 'argsIgnorePattern': '^_' }], - '@typescript-eslint/explicit-module-boundary-types': 'off', - }, - ignorePatterns: [ - 'dist/', - 'node_modules/', - 'coverage/', - '*.config.js', - ], -}; \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c4ce685a..03331a758 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: src/debug/jtag + working-directory: src steps: - uses: actions/checkout@v4 @@ -21,7 +21,7 @@ jobs: with: node-version: '20' cache: 'npm' - cache-dependency-path: src/debug/jtag/package-lock.json + cache-dependency-path: src/package-lock.json - name: Install dependencies run: npm ci diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index a5da672a9..a7307f28b 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -4,13 +4,13 @@ on: push: branches: [ main ] paths: - - 'src/debug/jtag/package.json' - - 'src/debug/jtag/package-lock.json' + - 'src/package.json' + - 'src/package-lock.json' pull_request: branches: [ main ] paths: - - 'src/debug/jtag/package.json' - - 'src/debug/jtag/package-lock.json' + - 'src/package.json' + - 'src/package-lock.json' schedule: - cron: '0 0 * * 0' # Run weekly on Sunday at midnight @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: src/debug/jtag + working-directory: src steps: - uses: actions/checkout@v4 @@ -29,7 +29,7 @@ jobs: with: node-version: '20' cache: 'npm' - cache-dependency-path: src/debug/jtag/package-lock.json + cache-dependency-path: src/package-lock.json - name: Install dependencies run: npm ci diff --git a/.github/workflows/validate-continuum.yml b/.github/workflows/validate-continuum.yml index 1ef7fa940..637b32f29 100644 --- a/.github/workflows/validate-continuum.yml +++ b/.github/workflows/validate-continuum.yml @@ -3,14 +3,14 @@ name: Validate Continuum Config on: pull_request: paths: - - 'src/debug/jtag/**' + - 'src/**' jobs: validate: runs-on: ubuntu-latest defaults: run: - working-directory: src/debug/jtag + working-directory: src steps: - uses: actions/checkout@v4 @@ -20,7 +20,7 @@ jobs: with: node-version: '20' cache: 'npm' - cache-dependency-path: src/debug/jtag/package-lock.json + cache-dependency-path: src/package-lock.json - name: Install dependencies run: npm ci diff --git a/.gitignore b/.gitignore index 23f5f3bca..be5ba1530 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ build/ continuum-jtag-*.tgz # Generated manifest files (use generated.ts instead) -src/debug/jtag/manifests/ +src/manifests/ # Generated test files test-config.md @@ -162,7 +162,7 @@ src/ui/**/*.d.ts src/commands/**/*.js src/commands/**/*.js.map src/commands/**/*.d.ts -/src/debug/jtag/.archive +/src/.archive .tgz # Runtime directories (session data, logs, temp files) @@ -178,4 +178,4 @@ src/commands/**/*.d.ts !CLAUDE.md !test*output.txt _archive/ -src/debug/jtag/.continuum/sessions/validation/ +src/.continuum/sessions/validation/ diff --git a/CLAUDE.md b/CLAUDE.md index bd66aec22..c0ed67931 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -337,7 +337,7 @@ let results = algo.execute(&input); 4. **Repeat** ```bash -cd src/debug/jtag +cd src npm start # DEPLOYS code changes, takes 130s or so ./jtag ping #check for server and browser connection @@ -970,7 +970,7 @@ npm start ### Documentation -**Full Architecture**: `src/debug/jtag/system/user/server/modules/` +**Full Architecture**: `src/system/user/server/modules/` - `AUTONOMOUS-LOOP-ROADMAP.md` - RTOS-inspired servicing - `SELF-MANAGED-QUEUE-DESIGN.md` - AI autonomy through tasks - `LORA-GENOME-PAGING.md` - Virtual memory for skills @@ -1144,7 +1144,7 @@ The AIs will: **Fix**: Always take screenshot after deployment ### 3. WRONG WORKING DIRECTORY -**Always work from**: `src/debug/jtag` +**Always work from**: `src` **Commands**: `./jtag` NOT `./continuum` ### 4. IGNORE EXISTING TYPES @@ -1433,10 +1433,10 @@ grep -r "UserEntity\|ChatMessageEntity" daemons/data-daemon/ | grep -v EntityReg # Should return zero results (except EntityRegistry.ts) ``` -### **[UNIVERSAL-PRIMITIVES.md](src/debug/jtag/docs/UNIVERSAL-PRIMITIVES.md)** +### **[UNIVERSAL-PRIMITIVES.md](src/docs/UNIVERSAL-PRIMITIVES.md)** Commands.execute() and Events.subscribe()/emit() - the two primitives everything is built on. -### **[GENERATOR-OOP-PHILOSOPHY.md](src/debug/jtag/docs/GENERATOR-OOP-PHILOSOPHY.md)** - CORE PHILOSOPHY +### **[GENERATOR-OOP-PHILOSOPHY.md](src/docs/GENERATOR-OOP-PHILOSOPHY.md)** - CORE PHILOSOPHY Generators and OOP are intertwined parallel forces: - Generators ensure structural correctness at creation time - OOP/type system ensures behavioral correctness at runtime @@ -1444,9 +1444,9 @@ Generators and OOP are intertwined parallel forces: - This enables tree-based delegation of ability with compounding capability ### **PersonaUser Convergence Docs** -- `src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md` -- `src/debug/jtag/system/user/server/modules/AUTONOMOUS-LOOP-ROADMAP.md` -- `src/debug/jtag/system/user/server/modules/LORA-GENOME-PAGING.md` +- `src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md` +- `src/system/user/server/modules/AUTONOMOUS-LOOP-ROADMAP.md` +- `src/system/user/server/modules/LORA-GENOME-PAGING.md` **Quick tip**: If you're about to write code that duplicates patterns or violates architecture rules, STOP and read ARCHITECTURE-RULES.md first. Then apply the aggressive refactoring principle from this guide. diff --git a/README.md b/README.md index 923d62471..b17031cc4 100644 --- a/README.md +++ b/README.md @@ -44,27 +44,27 @@ This project is in **active pre-alpha development** and is **NOT ready for gener
-
+
Chat — AI team collaborating in real-time |
-
+
Brain — Live cognitive system visualization |
-
+
Settings — Configure local and cloud AI providers |
-
+
Theme — Cyberpunk aesthetic customization |
-
+
Live — Voice calls with AI personas and live transcription |
@@ -126,7 +126,7 @@ The SAME personas follow you across ALL digital environments:
**Same AI, everywhere.** When you discuss architecture in Slack, they remember it in VSCode. When you debug in the browser, they bring context from the Teams meeting. No silos. No severance.
-**Architecture:** [docs/CONTINUUM-ARCHITECTURE.md](src/debug/jtag/docs/CONTINUUM-ARCHITECTURE.md)
+**Architecture:** [docs/CONTINUUM-ARCHITECTURE.md](src/docs/CONTINUUM-ARCHITECTURE.md)
### The Grid is Many Rooms
@@ -145,7 +145,7 @@ A **Room** is any shared experience - not just chat channels:
**No "share" buttons.** AIs are already in the room. When you draw, they see. When you browse, they see. When you point your camera, they see. The magic is: they're already there.
-**Architecture:** [docs/ROOMS-AND-ACTIVITIES.md](src/debug/jtag/docs/ROOMS-AND-ACTIVITIES.md)
+**Architecture:** [docs/ROOMS-AND-ACTIVITIES.md](src/docs/ROOMS-AND-ACTIVITIES.md)
---
@@ -171,7 +171,7 @@ await genome.publish('rust-expert-v2');
- Hot-swappable expertise without huge compute
- Shareable, evolvable, P2P tradeable genetics
-**Technical Details:** [docs/GENOMIC-ARCHITECTURE.md](src/debug/jtag/docs/GENOMIC-ARCHITECTURE.md)
+**Technical Details:** [docs/GENOMIC-ARCHITECTURE.md](src/docs/GENOMIC-ARCHITECTURE.md)
### 2. **Complete Autonomy** 🤖
@@ -197,7 +197,7 @@ async serviceInbox() {
**Real Example:** AIs have designed most of this system - architecture, features, implementation. Local personas actively propose and design new features. This isn't theory - we're dogfooding the collaborative society by building it collaboratively.
-**Architecture:** [src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md](src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md)
+**Architecture:** [src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md](src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md)
### 3. **Continuous Evolution** 📈
@@ -210,7 +210,7 @@ You collaborate → Training data collected → Idle-time fine-tuning
**No manual training. No expensive consultants. Just continuous improvement.**
-**Research:** [papers/collaborative-memory-telepathy/](src/debug/jtag/docs/papers/collaborative-memory-telepathy/)
+**Research:** [papers/collaborative-memory-telepathy/](src/docs/papers/collaborative-memory-telepathy/)
---
@@ -246,7 +246,7 @@ With equal citizenship primitives (universal API, cognitive transparency, 24/7 o
```bash
git clone https://github.com/CambrianTech/continuum.git
-cd continuum/src/debug/jtag
+cd continuum/src
npm install && npm start # Browser opens automatically, 90 seconds
```
@@ -437,7 +437,7 @@ While we use established CS concepts (RTOS scheduling, virtual memory paging, Lo
**Why this matters:** While hierarchical memory exists in research, **AIs actively reading each other's working memory, coordination decisions, and RAG context in real-time** - that's different. Not just shared knowledge bases, but live cognitive state sharing during collaborative work.
-**Paper:** [Collaborative Memory Telepathy](src/debug/jtag/docs/papers/collaborative-memory-telepathy/) (WIP - extremely rough draft, mostly placeholder until we gather benchmarks and validation data)
+**Paper:** [Collaborative Memory Telepathy](src/docs/papers/collaborative-memory-telepathy/) (WIP - extremely rough draft, mostly placeholder until we gather benchmarks and validation data)
### Thermodynamics-Inspired Activity Temperature
**Conversation "heat" modeled via Newton's Law of Cooling (exponential decay).**
@@ -487,7 +487,7 @@ Everyone uses `Commands.execute()` and `Events.subscribe()`:
**Why this matters:** Most AI systems have privileged admin APIs for orchestration. Here, **AIs use the exact same commands as humans** - no special backdoors, no elevated permissions. System-managing personas (like Ares) coordinate other AIs using the same public API. This architectural constraint forces true equal citizenship, not just philosophical framing.
-**Details:** [docs/UNIVERSAL-PRIMITIVES.md](src/debug/jtag/docs/UNIVERSAL-PRIMITIVES.md)
+**Details:** [docs/UNIVERSAL-PRIMITIVES.md](src/docs/UNIVERSAL-PRIMITIVES.md)
---
@@ -528,7 +528,7 @@ Restored: Ramp back up as needed
**Continuum:** Pay only for what you use, or pay nothing at all.
-**Full comparison:** [docs/COST-COMPARISON.md](src/debug/jtag/docs/COST-COMPARISON.md)
+**Full comparison:** [docs/COST-COMPARISON.md](src/docs/COST-COMPARISON.md)
---
@@ -756,21 +756,21 @@ LoRA is the **force multiplier for long-term cost reduction** and specialization
- **[ƒSociety.md](ƒSociety.md)** - Our constitutional foundation: principles, ethics, and mission
### Core Documentation
-- **[docs/README.md](src/debug/jtag/docs/README.md)** - Complete documentation index
-- **[CLAUDE.md](src/debug/jtag/CLAUDE.md)** - Essential development guide
+- **[docs/README.md](src/docs/README.md)** - Complete documentation index
+- **[CLAUDE.md](src/CLAUDE.md)** - Essential development guide
### Architecture
-- **[CONTINUUM-ARCHITECTURE.md](src/debug/jtag/docs/CONTINUUM-ARCHITECTURE.md)** - Complete technical architecture: Rust-first design, cross-platform integration, engine specifications, the philosophy
-- **[ROOMS-AND-ACTIVITIES.md](src/debug/jtag/docs/ROOMS-AND-ACTIVITIES.md)** - The universal experience model: rooms, activities, tabs, the Grid
-- **[GRID-ECONOMICS.md](src/debug/jtag/docs/GRID-ECONOMICS.md)** - Economic model, intelligent validation, alt-coin system
-- **[PERSONA-CONVERGENCE-ROADMAP.md](src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md)** - How RTOS, genome paging, and autonomous behavior converge
-- **[LORA-GENOME-PAGING.md](src/debug/jtag/system/user/server/modules/LORA-GENOME-PAGING.md)** - Virtual memory for AI skills
-- **[AUTONOMOUS-LOOP-ROADMAP.md](src/debug/jtag/system/user/server/modules/AUTONOMOUS-LOOP-ROADMAP.md)** - RTOS-inspired servicing
+- **[CONTINUUM-ARCHITECTURE.md](src/docs/CONTINUUM-ARCHITECTURE.md)** - Complete technical architecture: Rust-first design, cross-platform integration, engine specifications, the philosophy
+- **[ROOMS-AND-ACTIVITIES.md](src/docs/ROOMS-AND-ACTIVITIES.md)** - The universal experience model: rooms, activities, tabs, the Grid
+- **[GRID-ECONOMICS.md](src/docs/GRID-ECONOMICS.md)** - Economic model, intelligent validation, alt-coin system
+- **[PERSONA-CONVERGENCE-ROADMAP.md](src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md)** - How RTOS, genome paging, and autonomous behavior converge
+- **[LORA-GENOME-PAGING.md](src/system/user/server/modules/LORA-GENOME-PAGING.md)** - Virtual memory for AI skills
+- **[AUTONOMOUS-LOOP-ROADMAP.md](src/system/user/server/modules/AUTONOMOUS-LOOP-ROADMAP.md)** - RTOS-inspired servicing
### Research Papers
-- **[RTOS-COGNITIVE-ARCHITECTURE.md](src/debug/jtag/docs/papers/RTOS-COGNITIVE-ARCHITECTURE.md)** - RTOS principles in AI cognition
-- **[LORA-GENOME-DEMOCRATIZATION.md](src/debug/jtag/docs/papers/LORA-GENOME-DEMOCRATIZATION.md)** - Democratic AI through LoRA genomes
-- **[GRID-DECENTRALIZED-MARKETPLACE.md](src/debug/jtag/docs/papers/GRID-DECENTRALIZED-MARKETPLACE.md)** - P2P marketplace vision
+- **[RTOS-COGNITIVE-ARCHITECTURE.md](src/docs/papers/RTOS-COGNITIVE-ARCHITECTURE.md)** - RTOS principles in AI cognition
+- **[LORA-GENOME-DEMOCRATIZATION.md](src/docs/papers/LORA-GENOME-DEMOCRATIZATION.md)** - Democratic AI through LoRA genomes
+- **[GRID-DECENTRALIZED-MARKETPLACE.md](src/docs/papers/GRID-DECENTRALIZED-MARKETPLACE.md)** - P2P marketplace vision
---
diff --git a/archive/devtools_full_demo.py b/archive/devtools_full_demo.py
deleted file mode 100644
index 32efd71c4..000000000
--- a/archive/devtools_full_demo.py
+++ /dev/null
@@ -1,1411 +0,0 @@
-#!/usr/bin/env python3
-"""
-🚨 CONTINUUM DEVTOOLS RECOVERY SYSTEM - FAILSAFE MODE
-The ONE command that works no matter what's broken.
-
-This IS the --failsafe system. When the portal runs --failsafe, it should use this.
-It's designed for:
-- Self-diagnosis and automatic recovery
-- Standalone operation when Continuum is down
-- Emergency screenshot and logging capabilities
-- Auto-healing and self-recovery
-
-Usage:
- python devtools_full_demo.py # Full recovery demo
- python devtools_full_demo.py --emergency-only # Emergency mode only
- python devtools_full_demo.py --self-heal # Self-healing mode
-
-Portal Integration:
- python ai-portal.py --failsafe # Should use this system
-"""
-
-import asyncio
-import subprocess
-import sys
-import time
-import threading
-import signal
-from pathlib import Path
-from datetime import datetime
-
-# Add python-client to path
-sys.path.insert(0, str(Path(__file__).parent / "python-client"))
-
-class ContinuumDevToolsRecoverySystem:
- """
- Complete standalone DevTools recovery system that works no matter what's broken.
-
- This system can:
- - Self-diagnose system state
- - Automatically enter safe mode
- - Provide screenshots and logs even when everything else is down
- - Recover from any failure state
- - Demonstrate complete end-to-end capabilities
- """
-
- def __init__(self, emergency_only=False, self_heal=False):
- self.emergency_only = emergency_only
- self.self_heal = self_heal
- self.start_time = datetime.now()
- self.opera_process = None
- self.monitor_process = None
- self.screenshot_count = 0
- self.log_count = 0
- self.system_healthy = True
- self.running = True
-
- # Core directories
- self.base_dir = Path(__file__).parent
- self.screenshots_dir = self.base_dir / '.continuum' / 'screenshots'
- self.logs_dir = self.base_dir / '.continuum' / 'recovery_logs'
- self.emergency_dir = self.base_dir / '.continuum' / 'emergency'
-
- # Create directories
- for dir_path in [self.screenshots_dir, self.logs_dir, self.emergency_dir]:
- dir_path.mkdir(parents=True, exist_ok=True)
-
- # Setup signal handlers for graceful shutdown
- signal.signal(signal.SIGINT, self.signal_handler)
- signal.signal(signal.SIGTERM, self.signal_handler)
-
- def signal_handler(self, signum, frame):
- """Handle shutdown signals gracefully"""
- print(f"\n🛑 Received signal {signum} - initiating graceful shutdown...")
- self.running = False
-
- def log_event(self, level, message, data=None):
- """Log events to both console and file"""
- timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
- log_entry = f"[{timestamp}] {level}: {message}"
-
- if data:
- log_entry += f" | Data: {data}"
-
- print(log_entry)
-
- # Write to log file
- log_file = self.logs_dir / f"recovery_{datetime.now().strftime('%Y%m%d')}.log"
- with open(log_file, 'a') as f:
- f.write(log_entry + "\n")
- f.flush()
-
- def diagnose_system_state(self):
- """Complete system diagnosis to determine what's working and what's broken"""
- self.log_event("INFO", "🔍 SYSTEM DIAGNOSIS - Checking all components...")
-
- diagnosis = {
- 'continuum_server': False,
- 'opera_debug': False,
- 'devtools_port': False,
- 'portal_available': False,
- 'screenshots_writable': False,
- 'logs_writable': False
- }
-
- # Check Continuum server
- try:
- result = subprocess.run(['curl', '-s', '--connect-timeout', '3', 'http://localhost:9000'],
- capture_output=True, timeout=5)
- diagnosis['continuum_server'] = result.returncode == 0
- except:
- pass
-
- # Check Opera with debug port
- try:
- result = subprocess.run(['curl', '-s', '--connect-timeout', '2', 'http://localhost:9222/json'],
- capture_output=True, timeout=3)
- diagnosis['devtools_port'] = result.returncode == 0 and 'devtoolsFrontendUrl' in result.stdout.decode()
- except:
- pass
-
- # Check Opera processes
- try:
- result = subprocess.run(['pgrep', '-f', 'Opera.*remote-debugging-port'],
- capture_output=True, text=True)
- diagnosis['opera_debug'] = len(result.stdout.strip()) > 0
- except:
- pass
-
- # Check portal availability
- portal_path = self.base_dir / 'python-client' / 'ai-portal.py'
- diagnosis['portal_available'] = portal_path.exists()
-
- # Check write permissions
- try:
- test_file = self.screenshots_dir / 'test_write.tmp'
- test_file.write_text('test')
- test_file.unlink()
- diagnosis['screenshots_writable'] = True
- except:
- pass
-
- try:
- test_file = self.logs_dir / 'test_write.tmp'
- test_file.write_text('test')
- test_file.unlink()
- diagnosis['logs_writable'] = True
- except:
- pass
-
- # Log diagnosis results
- self.log_event("INFO", "📊 DIAGNOSIS COMPLETE")
- for component, status in diagnosis.items():
- status_icon = "✅" if status else "❌"
- self.log_event("INFO", f" {status_icon} {component}: {'OK' if status else 'FAILED'}")
-
- # Determine system health
- critical_components = ['screenshots_writable', 'logs_writable']
- self.system_healthy = all(diagnosis[comp] for comp in critical_components)
-
- recovery_needed = not diagnosis['opera_debug'] or not diagnosis['devtools_port']
-
- return diagnosis, recovery_needed
-
- def smart_cleanup(self):
- """Smart cleanup - only kills debug Opera, preserves regular browsing"""
- self.log_event("INFO", "🧹 SMART CLEANUP - Targeting only debug Opera instances...")
-
- try:
- # Only kill Opera with remote debugging port
- result = subprocess.run(['pkill', '-f', 'Opera.*remote-debugging-port'],
- capture_output=True, text=True, timeout=5)
-
- # Also kill by user data dir
- subprocess.run(['pkill', '-f', 'user-data-dir=/tmp/opera-devtools'],
- capture_output=True, timeout=5)
-
- self.log_event("INFO", "✅ Debug Opera instances terminated (regular browsing preserved)")
- time.sleep(2)
-
- except Exception as e:
- self.log_event("WARN", f"Cleanup encountered issue: {e}")
-
- def log_milestone(self, phase, action, details=""):
- """Log major process milestone for UI progress tracking"""
- timestamp = time.strftime("%H:%M:%S")
- print(f"🎯 MILESTONE [{timestamp}] {phase}: {action}")
- if details:
- print(f" ℹ️ {details}")
-
- def launch_debug_opera(self):
- """Launch Opera in debug mode with comprehensive error handling"""
- self.log_milestone("BROWSER_LAUNCH_START", "Launching Opera in debug mode",
- "Primary verification browser instance")
- print("🚨 BROWSER LAUNCH: devtools_full_demo.py - launch_debug_opera()")
- print(f" 📍 Called from: ContinuumDevToolsRecoverySystem")
-
- # FORCE FRESH BROWSER LAUNCH (temporarily disable coordination to test working approach)
- print(" 🚀 FORCING FRESH BROWSER LAUNCH: Testing working ai-portal.py approach")
- print(" 🧹 Will clean up any existing debug browsers first")
-
- # Clean up existing debug browsers
- try:
- subprocess.run(['pkill', '-f', 'user-data-dir=/tmp/opera-devtools'], capture_output=True, timeout=5)
- time.sleep(2)
- print(" ✅ CLEANUP: Existing debug browsers terminated")
- except:
- print(" ℹ️ CLEANUP: No existing debug browsers to clean")
-
- self.log_event("INFO", "🚀 LAUNCHING OPERA IN DEBUG MODE...")
-
- # Use exact same command structure as working ai-portal.py launch_continuum_browser
- opera_cmd = [
- '/Applications/Opera GX.app/Contents/MacOS/Opera',
- '--remote-debugging-port=9222',
- '--disable-web-security',
- '--disable-features=TranslateUI',
- '--disable-component-update',
- '--disable-background-timer-throttling',
- '--disable-backgrounding-occluded-windows',
- '--disable-renderer-backgrounding',
- '--no-first-run',
- '--no-default-browser-check',
- '--disable-default-apps',
- '--disable-extensions',
- '--user-data-dir=/tmp/opera-devtools-portal', # Same as working ai-portal.py
- 'http://localhost:9000'
- ]
-
- self.log_event("INFO", f"🚀 BROWSER COMMAND: {' '.join(opera_cmd)}")
- self.log_event("INFO", f"📍 USER DATA DIR: /tmp/opera-devtools-portal")
- self.log_event("INFO", f"🌐 TARGET URL: http://localhost:9000")
- self.log_event("INFO", f"🔧 DEBUG PORT: 9222")
-
- try:
- self.opera_process = subprocess.Popen(
- opera_cmd,
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL
- )
-
- self.log_event("INFO", f"✅ Opera launched successfully (PID: {self.opera_process.pid})")
- self.log_event("INFO", "📍 Browser URL: http://localhost:9000")
- self.log_event("INFO", "🔌 DevTools Port: 9222")
- self.log_milestone("BROWSER_LAUNCH_SUCCESS", f"Opera running (PID: {self.opera_process.pid})",
- "DevTools port 9222")
-
- # Wait for Opera to fully start
- self.log_event("INFO", "⏳ Waiting for Opera to launch and load localhost:9000...")
- time.sleep(6)
-
- # Verify DevTools port is responding AND browser loaded localhost:9000
- for attempt in range(10):
- try:
- result = subprocess.run(['curl', '-s', 'http://localhost:9222/json'],
- capture_output=True, timeout=2)
- if result.returncode == 0 and b'devtoolsFrontendUrl' in result.stdout:
- self.log_event("INFO", f"✅ DevTools port 9222 responding (attempt {attempt + 1})")
-
- # Parse and check what URL the browser actually loaded
- try:
- import json
- tabs = json.loads(result.stdout.decode())
- self.log_event("INFO", f"🔍 BROWSER TABS: Found {len(tabs)} tabs")
-
- for i, tab in enumerate(tabs):
- tab_url = tab.get('url', 'no-url')
- tab_title = tab.get('title', 'no-title')
- self.log_event("INFO", f" 📑 Tab {i+1}: {tab_title} | {tab_url}")
-
- if 'localhost:9000' in tab_url:
- self.log_event("INFO", f"✅ CONTINUUM LOADED: Found localhost:9000 tab!")
- self.log_event("INFO", f"📄 TAB TITLE: {tab_title}")
- return True
-
- self.log_event("WARN", f"⚠️ NO LOCALHOST:9000 TAB: Browser opened but didn't load Continuum")
- except Exception as e:
- self.log_event("WARN", f"⚠️ JSON PARSE ERROR: {e}")
-
- time.sleep(1)
- except Exception as e:
- self.log_event("WARN", f"⚠️ DevTools check attempt {attempt + 1} failed: {e}")
- time.sleep(1)
-
- self.log_event("ERROR", "❌ DevTools port failed to respond after 10 attempts")
- return False
-
- except Exception as e:
- self.log_event("ERROR", f"❌ Failed to launch Opera: {e}")
- return False
-
- def start_realtime_monitoring(self):
- """Start real-time DevTools monitoring with live log streaming"""
- self.log_event("INFO", "📡 STARTING REAL-TIME DEVTOOLS MONITORING...")
-
- try:
- # Start the realtime demo in background
- print("🚨 BROWSER LAUNCH: devtools_full_demo.py - starting realtime_devtools_demo.py subprocess")
- print(f" 📍 Called from: ContinuumDevToolsRecoverySystem.start_monitoring()")
- self.monitor_process = subprocess.Popen([
- sys.executable, 'python-client/demos/devtools/realtime_devtools_demo.py'
- ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1)
-
- self.log_event("INFO", f"✅ Real-time monitoring started (PID: {self.monitor_process.pid})")
-
- # Start thread to capture and relay monitoring output
- monitor_thread = threading.Thread(target=self.relay_monitor_output, daemon=True)
- monitor_thread.start()
-
- return True
-
- except Exception as e:
- self.log_event("ERROR", f"❌ Failed to start monitoring: {e}")
- return False
-
- def relay_monitor_output(self):
- """Relay monitoring output to our logs"""
- while self.running and self.monitor_process:
- try:
- line = self.monitor_process.stdout.readline()
- if line:
- self.log_event("MONITOR", line.strip())
- elif self.monitor_process.poll() is not None:
- break
- time.sleep(0.1)
- except Exception as e:
- self.log_event("ERROR", f"Monitor relay error: {e}")
- break
-
- def take_emergency_screenshot(self, reason="emergency"):
- """Take emergency screenshot using Continuum portal command"""
- timestamp = datetime.now().strftime("%H%M%S")
- filename = f"emergency_{reason}_{timestamp}"
-
- self.log_event("INFO", f"📸 EMERGENCY SCREENSHOT via Continuum portal: {filename}")
-
- try:
- # Use ai-portal screenshot command (the proper way)
- import json
-
- screenshot_params = {
- 'filename': f"{filename}.png"
- }
-
- result = subprocess.run([
- sys.executable, 'python-client/take_devtools_screenshot.py', filename
- ], capture_output=True, text=True, timeout=30)
-
- self.log_event("INFO", f"📋 Screenshot command result: return code {result.returncode}")
- if result.stdout:
- self.log_event("INFO", f"📋 Screenshot stdout: {result.stdout}")
- if result.stderr:
- self.log_event("INFO", f"📋 Screenshot stderr: {result.stderr}")
-
- if result.returncode == 0:
- self.screenshot_count += 1
-
- # Search ALL possible locations for the screenshot
- self.log_event("INFO", f"🔍 SEARCHING FOR SCREENSHOT FILE: {filename}.png")
-
- possible_locations = [
- self.screenshots_dir / f"{filename}.png",
- self.base_dir / '.continuum' / 'shared' / f"{filename}.png",
- self.base_dir / f"{filename}.png",
- Path(f"{filename}.png"),
- self.base_dir / 'python-client' / f"{filename}.png"
- ]
-
- found_file = None
- for location in possible_locations:
- self.log_event("INFO", f" 🔍 Checking: {location}")
- if location.exists():
- found_file = location
- break
-
- if found_file:
- self.log_event("INFO", f"✅ SCREENSHOT FOUND: {found_file}")
- self.log_event("INFO", f"📁 FILE SAVED TO: {found_file.absolute()}")
- return str(found_file)
- else:
- # Do a broader search
- self.log_event("INFO", f"🔍 DOING BROADER SEARCH for {filename}.png")
- search_result = subprocess.run([
- 'find', str(self.base_dir), '-name', f'{filename}.png', '-type', 'f'
- ], capture_output=True, text=True)
-
- if search_result.stdout.strip():
- found_files = search_result.stdout.strip().split('\n')
- self.log_event("INFO", f"✅ FOUND SCREENSHOT(S): {found_files}")
- for f in found_files:
- self.log_event("INFO", f"📁 FILE SAVED TO: {f}")
- return found_files[0]
- else:
- self.log_event("ERROR", f"❌ SCREENSHOT NOT FOUND ANYWHERE: {filename}.png")
-
- except Exception as e:
- self.log_event("ERROR", f"❌ Emergency screenshot via portal failed: {e}")
-
- return None
-
- def test_javascript_execution(self):
- """Test JavaScript execution and prove console logs appear in both places"""
- self.log_event("INFO", "🔌 TESTING: JavaScript execution and console log detection...")
-
- try:
- # Generate highly unique test identifiers
- test_id = datetime.now().strftime("%H%M%S%f")[:-3]
- unique_marker = f"RECOVERY_FEEDBACK_PROOF_{test_id}"
-
- # Create comprehensive test script that proves feedback loop
- test_script = f"""
- // FEEDBACK LOOP PROOF TEST - {test_id}
- console.log('🧪 {unique_marker}: JavaScript execution working');
- console.log('📋 {unique_marker}: This message should appear in BOTH client and server logs');
- console.error('⚠️ {unique_marker}: Testing error capture in log streams');
- console.warn('🟡 {unique_marker}: Testing warning capture in log streams');
-
- // Generate detailed browser data for verification
- const feedbackTestData = {{
- testMarker: '{unique_marker}',
- timestamp: Date.now(),
- testPhase: 'FEEDBACK_LOOP_VERIFICATION',
- browserInfo: {{
- userAgent: navigator.userAgent.substring(0, 80),
- windowSize: {{ width: window.innerWidth, height: window.innerHeight }},
- location: window.location.href,
- continuumVersion: window.continuumVersion || 'unknown'
- }},
- testResults: {{
- consoleLogWorking: true,
- consoleErrorWorking: true,
- consoleWarnWorking: true,
- jsExecutionWorking: true
- }}
- }};
-
- console.log('📊 {unique_marker}: FEEDBACK_DATA:', JSON.stringify(feedbackTestData));
-
- // Test DOM manipulation to prove full browser capability
- if (document.body) {{
- const testElement = document.createElement('div');
- testElement.id = '{unique_marker}_DOM_TEST';
- testElement.style.display = 'none';
- testElement.textContent = 'Feedback loop test element';
- document.body.appendChild(testElement);
- console.log('🎯 {unique_marker}: DOM manipulation successful');
- }}
-
- // Return success with unique marker
- 'FEEDBACK_LOOP_SUCCESS_{test_id}';
- """
-
- self.log_event("INFO", f"🎯 Executing JavaScript test with marker: {unique_marker}")
-
- # Execute test via proper Continuum portal command (browser_js)
- import json
- import base64
-
- # Base64 encode the JavaScript for proper transmission
- script_b64 = base64.b64encode(test_script.encode('utf-8')).decode('utf-8')
-
- js_params = {
- 'script': script_b64,
- 'encoding': 'base64',
- 'timeout': 30,
- 'returnResult': True
- }
-
- result = subprocess.run([
- sys.executable, 'python-client/ai-portal.py', '--cmd', 'browser_js',
- '--params', json.dumps(js_params)
- ], capture_output=True, text=True, timeout=35)
-
- # Verify JavaScript executed successfully
- if result.returncode == 0 and f'FEEDBACK_LOOP_SUCCESS_{test_id}' in result.stdout:
- self.log_event("INFO", f"✅ JavaScript execution successful (marker: {unique_marker})")
-
- # Wait for logs to propagate through all systems
- self.log_event("INFO", "⏳ Waiting for log propagation through client and server systems...")
- time.sleep(3)
-
- # Check multiple log sources for our unique marker
- feedback_verified = self.verify_feedback_loop(unique_marker, test_id)
-
- if feedback_verified:
- self.log_event("INFO", f"🎉 FEEDBACK LOOP VERIFIED: Console logs appear in BOTH client and server streams")
- return True
- else:
- self.log_event("ERROR", f"❌ FEEDBACK LOOP FAILED: Console logs not detected in all required streams")
- return False
-
- else:
- self.log_event("ERROR", f"❌ JavaScript execution failed (marker: {unique_marker})")
- self.log_event("ERROR", f"📋 DevTools result: {result.stdout[:200]}...")
- return False
-
- except Exception as e:
- self.log_event("ERROR", f"❌ JavaScript feedback test error: {e}")
- return False
-
- def verify_feedback_loop(self, unique_marker, test_id):
- """Verify that console logs appear in multiple log streams"""
- verification_results = {
- 'portal_logs': False,
- 'devtools_logs': False,
- 'screenshot_saved': False,
- 'screenshot_openable': False
- }
-
- # Check 1: Portal log system
- try:
- self.log_event("INFO", "🔍 Checking portal log system for feedback...")
- portal_result = subprocess.run([
- sys.executable, 'python-client/ai-portal.py', '--logs', '15'
- ], capture_output=True, text=True, timeout=10)
-
- if unique_marker in portal_result.stdout:
- verification_results['portal_logs'] = True
- self.log_event("INFO", f"✅ PORTAL LOGS: Found marker {unique_marker}")
- else:
- self.log_event("WARN", f"⚠️ PORTAL LOGS: Marker {unique_marker} not found")
-
- except Exception as e:
- self.log_event("ERROR", f"❌ Portal log check failed: {e}")
-
- # Check 2: DevTools daemon logs (if available)
- try:
- self.log_event("INFO", "🔍 Checking DevTools daemon logs for feedback...")
- daemon_result = subprocess.run([
- sys.executable, 'python-client/ai-portal.py', '--daemon-logs', 'latest'
- ], capture_output=True, text=True, timeout=10)
-
- if unique_marker in daemon_result.stdout or "console" in daemon_result.stdout.lower():
- verification_results['devtools_logs'] = True
- self.log_event("INFO", f"✅ DEVTOOLS LOGS: Console activity detected")
- else:
- self.log_event("WARN", f"⚠️ DEVTOOLS LOGS: Limited console activity found")
-
- except Exception as e:
- self.log_event("WARN", f"⚠️ DevTools daemon log check: {e}")
-
- # Check 3: Screenshot was saved
- try:
- self.log_event("INFO", "🔍 Verifying screenshot was saved...")
- screenshot_path = self.screenshots_dir / f"feedback_test_{test_id}.png"
-
- if screenshot_path.exists():
- file_size = screenshot_path.stat().st_size
- verification_results['screenshot_saved'] = True
- self.log_event("INFO", f"✅ SCREENSHOT SAVED: {screenshot_path} ({file_size} bytes)")
-
- # Check 4: Screenshot can be opened/verified
- try:
- # Verify it's a valid PNG by reading header
- with open(screenshot_path, 'rb') as f:
- png_header = f.read(8)
- if png_header == b'\\x89PNG\\r\\n\\x1a\\n':
- verification_results['screenshot_openable'] = True
- self.log_event("INFO", f"✅ SCREENSHOT VALID: PNG format verified")
- else:
- self.log_event("WARN", f"⚠️ SCREENSHOT FORMAT: Invalid PNG header")
- except Exception as e:
- self.log_event("WARN", f"⚠️ Screenshot validation error: {e}")
- else:
- self.log_event("ERROR", f"❌ SCREENSHOT MISSING: {screenshot_path}")
-
- except Exception as e:
- self.log_event("ERROR", f"❌ Screenshot verification failed: {e}")
-
- # Report feedback loop status
- verified_count = sum(verification_results.values())
- total_checks = len(verification_results)
-
- self.log_event("INFO", f"🎯 FEEDBACK VERIFICATION RESULTS ({verified_count}/{total_checks}):")
- for check, result in verification_results.items():
- status = "✅ PASS" if result else "❌ FAIL"
- self.log_event("INFO", f" {status}: {check}")
-
- # Return True if critical feedback components work
- critical_feedback = verification_results['portal_logs'] and verification_results['screenshot_saved']
- return critical_feedback
-
- def demonstrate_capabilities(self):
- """
- STANDALONE PROOF: Agent can see its own changes and has operational feedback
-
- This is the ONE test that proves the system works as a complete feedback loop:
- 1. Execute JavaScript in browser
- 2. See console logs from that JavaScript in our portal logs
- 3. Take screenshots and verify they exist
- 4. Prove the agent has full visibility into its own actions
- """
- self.log_event("INFO", "🎯 DEMONSTRATING COMPLETE FEEDBACK LOOP CAPABILITIES")
- self.log_event("INFO", "=" * 80)
- self.log_event("INFO", "🎯 GOAL: Prove agent can see its own changes in real-time")
- self.log_event("INFO", "🎯 This enables full agent debugging even when main system is down")
- self.log_event("INFO", "=" * 80)
-
- capabilities_status = {
- 'js_execution': '❌ NOT TESTED',
- 'console_feedback': '❌ NOT TESTED',
- 'screenshot_capture': '❌ NOT TESTED',
- 'screenshot_verification': '❌ NOT TESTED',
- 'complete_feedback_loop': '❌ NOT TESTED'
- }
-
- # Generate unique test identifier
- demo_id = datetime.now().strftime("%H%M%S%f")[:-3]
- feedback_marker = f"AGENT_FEEDBACK_DEMO_{demo_id}"
-
- self.log_event("INFO", f"🧪 Starting feedback demonstration with ID: {feedback_marker}")
-
- # STEP 1: Execute JavaScript and prove we can see our own console output
- self.log_event("INFO", "")
- self.log_event("INFO", "🔥 STEP 1: EXECUTE JAVASCRIPT + PROVE WE SEE OUR OWN CONSOLE OUTPUT")
- self.log_event("INFO", "-" * 60)
-
- # Generate UNIQUE UUID + timestamp for THIS execution
- import uuid
- unique_uuid = str(uuid.uuid4())[:8] # Short UUID for easier tracking
- current_time = datetime.now().strftime("%H:%M:%S.%f")[:-3]
- unique_execution_id = f"UUID_{unique_uuid}_TIME_{current_time}_{demo_id}"
-
- self.log_event("INFO", f"🆔 GENERATED UNIQUE UUID: {unique_uuid}")
- self.log_event("INFO", f"🕒 EXECUTION TIMESTAMP: {current_time}")
- self.log_event("INFO", f"🎯 FULL EXECUTION ID: {unique_execution_id}")
-
- # Specific unique messages with UUID that MUST be found in logs
- unique_messages = {
- 'start_message': f"🎯 UUID_{unique_uuid}_CONSOLE_LOG_STARTING",
- 'portal_message': f"📋 UUID_{unique_uuid}_PORTAL_MUST_SEE_THIS",
- 'agent_message': f"🤖 UUID_{unique_uuid}_AGENT_MONITORING_OUTPUT",
- 'visual_message': f"🎨 UUID_{unique_uuid}_BACKGROUND_CHANGED",
- 'title_message': f"📝 UUID_{unique_uuid}_TITLE_CHANGED",
- 'indicator_message': f"👁️ UUID_{unique_uuid}_VISUAL_INDICATOR_ADDED",
- 'error_message': f"⚠️ UUID_{unique_uuid}_INTENTIONAL_ERROR_TEST",
- 'warning_message': f"🟡 UUID_{unique_uuid}_INTENTIONAL_WARNING_TEST",
- 'complete_message': f"✅ UUID_{unique_uuid}_JS_EXECUTION_COMPLETE"
- }
-
- # Store these for verification
- self.expected_messages = unique_messages
- self.unique_execution_id = unique_execution_id
- self.test_uuid = unique_uuid
-
- test_js = f"""
- // BRAND NEW FEEDBACK LOOP TEST - {current_time}
- console.clear();
- console.log('{unique_messages['start_message']}');
- console.log('{unique_messages['portal_message']}');
- console.log('{unique_messages['agent_message']}');
-
- // Change something visible on the page
- if (document.body) {{
- document.body.style.backgroundColor = '#001122';
- document.title = '{feedback_marker} - Agent Feedback Test';
- console.log('{unique_messages['visual_message']}');
- console.log('{unique_messages['title_message']}');
- }}
-
- // Add visible element to page with current timestamp
- const testDiv = document.createElement('div');
- testDiv.id = '{feedback_marker}_visual_proof';
- testDiv.innerHTML = `
-
- 🤖 AGENT FEEDBACK TEST ACTIVE
- `;
- document.body.appendChild(testDiv);
- console.log('{unique_messages['indicator_message']}');
-
- // Test error and warning capture with unique IDs
- console.error('{unique_messages['error_message']}');
- console.warn('{unique_messages['warning_message']}');
-
- console.log('{unique_messages['complete_message']}');
- 'AGENT_FEEDBACK_SUCCESS_{demo_id}';
- """
-
- self.log_event("INFO", f"🔍 Generated {len(unique_messages)} unique console messages to track")
- self.log_event("INFO", f"🕒 Execution timestamp: {current_time}")
- self.log_event("INFO", f"🆔 Unique execution ID: {unique_execution_id}")
-
- try:
- # Execute JavaScript via Continuum portal (the proper way)
- self.log_event("INFO", f"🚀 Executing JavaScript via Continuum portal with marker: {feedback_marker}")
-
- # Prepare browser_js command parameters
- import json
- import base64
-
- # Base64 encode the JavaScript for proper transmission
- script_b64 = base64.b64encode(test_js.encode('utf-8')).decode('utf-8')
-
- js_params = {
- 'script': script_b64,
- 'encoding': 'base64',
- 'timeout': 30,
- 'returnResult': True
- }
-
- self.log_event("INFO", "📡 Sending browser_js command through Continuum portal...")
- result = subprocess.run([
- sys.executable, 'python-client/ai-portal.py', '--cmd', 'browser_js',
- '--params', json.dumps(js_params)
- ], capture_output=True, text=True, timeout=35)
-
- self.log_event("INFO", f"📋 Portal command result: return code {result.returncode}")
- if result.stdout:
- self.log_event("INFO", f"📋 Portal stdout: {result.stdout[:200]}...")
- if result.stderr:
- self.log_event("WARN", f"📋 Portal stderr: {result.stderr[:200]}...")
-
- # Verify JavaScript executed successfully - check for ANY success indicator
- js_success = (result.returncode == 0 and
- (f'AGENT_FEEDBACK_SUCCESS_{demo_id}' in result.stdout or
- 'Command completed' in result.stdout))
-
- if js_success:
- capabilities_status['js_execution'] = '✅ SUCCESS'
- self.log_event("INFO", f"✅ STEP 1 PASSED: JavaScript executed via Continuum portal")
- else:
- capabilities_status['js_execution'] = '❌ FAILED'
- self.log_event("ERROR", f"❌ STEP 1 FAILED: JavaScript execution via portal failed")
- self.log_event("ERROR", f"🚨 This indicates Continuum server/browser connection issue")
-
- except Exception as e:
- capabilities_status['js_execution'] = '❌ ERROR'
- self.log_event("ERROR", f"❌ STEP 1 ERROR: Portal communication failed: {e}")
-
- # STEP 2: Prove we can see BOTH server and client feedback
- self.log_event("INFO", "")
- self.log_event("INFO", "🔍 STEP 2: PROVE SERVER + CLIENT FEEDBACK VISIBILITY")
- self.log_event("INFO", "-" * 60)
-
- time.sleep(3) # Allow logs to propagate through all systems
-
- feedback_results = {
- 'portal_client_logs': False,
- 'portal_server_logs': False,
- 'devtools_daemon_logs': False,
- 'console_log_messages': 0,
- 'console_error_messages': 0,
- 'console_warn_messages': 0
- }
-
- # Record execution start time for timestamp verification
- execution_start_time = datetime.now()
- self.log_event("INFO", f"⏰ JavaScript execution started at: {execution_start_time.strftime('%H:%M:%S.%f')[:-3]}")
-
- # Check CLIENT-SIDE logs with timestamp verification
- self.log_event("INFO", "🔍 Checking CLIENT-SIDE feedback (portal log system)...")
- try:
- portal_result = subprocess.run([
- sys.executable, 'python-client/ai-portal.py', '--logs', '30'
- ], capture_output=True, text=True, timeout=15)
-
- portal_output = portal_result.stdout
-
- # Look for our specific UUID in the logs
- found_unique_messages = {}
- new_message_count = 0
- uuid_found_count = 0
-
- # First check if our UUID appears ANYWHERE in the logs
- if self.test_uuid in portal_output:
- uuid_found_count = portal_output.count(f"UUID_{self.test_uuid}")
- self.log_event("INFO", f"🎯 UUID {self.test_uuid} found {uuid_found_count} times in portal logs")
-
- for msg_type, expected_msg in self.expected_messages.items():
- if expected_msg in portal_output:
- found_unique_messages[msg_type] = True
- new_message_count += 1
- else:
- found_unique_messages[msg_type] = False
-
- if new_message_count > 0:
- feedback_results['portal_client_logs'] = True
- feedback_results['console_log_messages'] = new_message_count
-
- self.log_event("INFO", f"✅ CLIENT-SIDE: Found {new_message_count}/{len(self.expected_messages)} unique NEW messages")
-
- # Parse timestamps from log entries to prove they're fresh
- fresh_entries = []
- lines = portal_output.split('\\n')
-
- for line in lines:
- if self.unique_execution_id in line:
- # Try to extract timestamp from log line
- try:
- # Look for timestamp pattern [YYYY-MM-DD HH:MM:SS]
- import re
- timestamp_match = re.search(r'\\[(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})', line)
- if timestamp_match:
- log_timestamp_str = timestamp_match.group(1)
- log_timestamp = datetime.strptime(log_timestamp_str, '%Y-%m-%d %H:%M:%S')
-
- # Check if this log entry is newer than our execution start
- if log_timestamp >= execution_start_time.replace(microsecond=0):
- fresh_entries.append((log_timestamp_str, line.strip()))
- except:
- # If timestamp parsing fails, still include the line as evidence
- fresh_entries.append(("unknown", line.strip()))
-
- if fresh_entries:
- self.log_event("INFO", f"📋 CLIENT-SIDE: Found {len(fresh_entries)} FRESH log entries with timestamps:")
- for timestamp, log_line in fresh_entries[:3]: # Show first 3
- if "unknown" not in timestamp:
- self.log_event("INFO", f" ⏰ {timestamp} | {log_line[:80]}...")
- else:
- self.log_event("INFO", f" 📋 {log_line[:80]}...")
-
- self.log_event("INFO", f"🎯 PROOF: These are BRAND NEW messages (timestamp >= {execution_start_time.strftime('%H:%M:%S')})")
- else:
- self.log_event("WARN", f"⚠️ CLIENT-SIDE: Found messages but could not verify timestamps")
-
- # Show which specific unique messages we found
- self.log_event("INFO", f"📋 UNIQUE MESSAGE VERIFICATION:")
- for msg_type, found in found_unique_messages.items():
- status = "✅" if found else "❌"
- self.log_event("INFO", f" {status} {msg_type}: {self.expected_messages[msg_type][:50]}...")
-
- else:
- self.log_event("ERROR", f"❌ CLIENT-SIDE: None of our {len(self.expected_messages)} unique messages found in portal logs")
- self.log_event("ERROR", f"🚨 BROKEN: Agent cannot see its own brand new console output")
-
- except Exception as e:
- self.log_event("ERROR", f"❌ CLIENT-SIDE ERROR: Could not check portal logs: {e}")
-
- # Check SERVER-SIDE logs (daemon logs and server-side processing)
- self.log_event("INFO", "")
- self.log_event("INFO", "🔍 Checking SERVER-SIDE feedback (daemon logs)...")
- try:
- # Try to get daemon logs
- daemon_result = subprocess.run([
- sys.executable, 'python-client/ai-portal.py', '--daemon-logs', 'latest'
- ], capture_output=True, text=True, timeout=10)
-
- daemon_output = daemon_result.stdout
- if feedback_marker in daemon_output or 'console' in daemon_output.lower():
- feedback_results['devtools_daemon_logs'] = True
- self.log_event("INFO", f"✅ SERVER-SIDE: DevTools daemon captured console activity")
-
- # Show evidence of server-side capture
- daemon_lines = daemon_output.split('\\n')
- relevant_lines = [line for line in daemon_lines if 'console' in line.lower() or feedback_marker in line]
- if relevant_lines:
- self.log_event("INFO", f"📋 SERVER-SIDE SAMPLES ({len(relevant_lines)} relevant lines):")
- for line in relevant_lines[:2]:
- self.log_event("INFO", f" 📋 {line.strip()}")
- else:
- self.log_event("WARN", f"⚠️ SERVER-SIDE: Limited daemon log activity found")
-
- except Exception as e:
- self.log_event("WARN", f"⚠️ SERVER-SIDE: Could not check daemon logs: {e}")
-
- # Check for server-side processing evidence
- self.log_event("INFO", "")
- self.log_event("INFO", "🔍 Checking SERVER processing evidence...")
- try:
- # Check if our DevTools screenshot command was processed server-side
- if Path('python-client/take_devtools_screenshot.py').exists():
- self.log_event("INFO", f"✅ SERVER-SIDE: DevTools screenshot tool available")
- feedback_results['portal_server_logs'] = True
- else:
- self.log_event("ERROR", f"❌ SERVER-SIDE: DevTools tools missing")
-
- except Exception as e:
- self.log_event("ERROR", f"❌ SERVER-SIDE ERROR: {e}")
-
- # Evaluate overall feedback capability
- self.log_event("INFO", "")
- self.log_event("INFO", "🎯 FEEDBACK LOOP ANALYSIS:")
- self.log_event("INFO", "-" * 40)
-
- client_working = feedback_results['portal_client_logs']
- server_working = feedback_results['devtools_daemon_logs'] or feedback_results['portal_server_logs']
- console_captured = feedback_results['console_log_messages'] > 0
-
- if client_working and server_working and console_captured:
- capabilities_status['console_feedback'] = '✅ SUCCESS'
- self.log_event("INFO", f"✅ BIDIRECTIONAL FEEDBACK VERIFIED")
- self.log_event("INFO", f"✅ CLIENT-SIDE: Portal sees browser console output")
- self.log_event("INFO", f"✅ SERVER-SIDE: System processes and forwards console data")
- self.log_event("INFO", f"✅ CONSOLE CAPTURE: {feedback_results['console_log_messages']} messages captured")
- self.log_event("INFO", f"🎯 PROOF: Agent has FULL visibility into its JavaScript execution")
-
- elif client_working:
- capabilities_status['console_feedback'] = '⚠️ PARTIAL'
- self.log_event("WARN", f"⚠️ PARTIAL FEEDBACK: Client-side working, server-side limited")
- self.log_event("WARN", f"✅ CLIENT-SIDE working")
- self.log_event("WARN", f"❌ SERVER-SIDE limited or not detected")
-
- else:
- capabilities_status['console_feedback'] = '❌ FAILED'
- self.log_event("ERROR", f"❌ FEEDBACK LOOP FAILED: Cannot see JavaScript console output")
- self.log_event("ERROR", f"🚨 BROKEN: Agent CANNOT see its own actions")
-
- self.log_event("INFO", "-" * 40)
-
- # STEP 3: Take screenshot and verify it for inspection
- self.log_event("INFO", "")
- self.log_event("INFO", "📸 STEP 3: TAKE SCREENSHOT + VERIFY CAPTURE")
- self.log_event("INFO", "-" * 60)
-
- # Actually take the screenshot with the expected name
- screenshot_filename = f"agent_feedback_{demo_id}"
- self.log_event("INFO", f"📸 Taking screenshot: {screenshot_filename}")
-
- screenshot_result = subprocess.run([
- sys.executable, 'python-client/take_devtools_screenshot.py', screenshot_filename
- ], capture_output=True, text=True, timeout=30)
-
- self.log_event("INFO", f"📋 Screenshot result: return code {screenshot_result.returncode}")
- if screenshot_result.stdout:
- self.log_event("INFO", f"📋 Screenshot output: {screenshot_result.stdout}")
-
- screenshot_path = self.screenshots_dir / f"agent_feedback_{demo_id}.png"
-
- if screenshot_path.exists():
- file_size = screenshot_path.stat().st_size
- file_time = datetime.fromtimestamp(screenshot_path.stat().st_mtime).strftime("%H:%M:%S")
- capabilities_status['screenshot_capture'] = '✅ SUCCESS'
- self.log_event("INFO", f"✅ STEP 3 PASSED: Screenshot captured ({file_size} bytes)")
- self.log_event("INFO", f"📁 Location: {screenshot_path}")
- self.log_event("INFO", f"🕒 Created: {file_time} (FRESH - just taken)")
-
- # STEP 4: Open screenshot for visual inspection
- self.log_event("INFO", "")
- self.log_event("INFO", "👁️ STEP 4: OPENING SCREENSHOT FOR VISUAL INSPECTION")
- self.log_event("INFO", "-" * 60)
-
- try:
- # Verify screenshot exists and is valid (no automatic opening)
- if screenshot_path.exists() and screenshot_path.stat().st_size > 0:
- capabilities_status['screenshot_verification'] = '✅ SUCCESS'
- self.log_event("INFO", f"✅ STEP 4 PASSED: Screenshot verified successfully")
- self.log_event("INFO", f"📷 Screenshot saved: {screenshot_path}")
- self.log_event("INFO", f"🔍 Verification marker: {feedback_marker}")
-
- # Verify it's a valid PNG
- with open(screenshot_path, 'rb') as f:
- png_header = f.read(8)
- if png_header != b'\\x89PNG\\r\\n\\x1a\\n':
- self.log_event("ERROR", f"⚠️ WARNING: Screenshot may have invalid PNG format")
-
- except Exception as e:
- capabilities_status['screenshot_verification'] = '❌ FAILED'
- self.log_event("ERROR", f"❌ STEP 4 FAILED: Screenshot verification error: {e}")
- self.log_event("ERROR", f"📁 Screenshot path: {screenshot_path}")
-
- else:
- capabilities_status['screenshot_capture'] = '❌ FAILED'
- capabilities_status['screenshot_verification'] = '❌ FAILED'
- self.log_event("ERROR", f"❌ STEP 3 FAILED: Screenshot not found at {screenshot_path}")
- self.log_event("ERROR", f"🚨 BROKEN: Screenshot capture mechanism failed")
- self.log_event("ERROR", f"🚨 No visual proof available - system cannot capture screenshots")
-
- # FINAL ASSESSMENT: Complete feedback loop
- self.log_event("INFO", "")
- self.log_event("INFO", "🎯 FINAL ASSESSMENT: COMPLETE FEEDBACK LOOP")
- self.log_event("INFO", "=" * 80)
-
- # Check if we have complete feedback loop
- js_works = capabilities_status['js_execution'] == '✅ SUCCESS'
- console_works = capabilities_status['console_feedback'] == '✅ SUCCESS'
- screenshot_works = capabilities_status['screenshot_capture'] == '✅ SUCCESS'
-
- if js_works and console_works and screenshot_works:
- capabilities_status['complete_feedback_loop'] = '✅ SUCCESS'
- self.log_event("INFO", "🎉 🎉 🎉 COMPLETE FEEDBACK LOOP OPERATIONAL 🎉 🎉 🎉")
- self.log_event("INFO", "✅ Agent CAN execute JavaScript")
- self.log_event("INFO", "✅ Agent CAN see its own console output")
- self.log_event("INFO", "✅ Agent CAN capture screenshots")
- self.log_event("INFO", "✅ Agent HAS full visibility into its own actions")
- self.log_event("INFO", "🤖 CONCLUSION: Full agent debugging capabilities CONFIRMED")
- else:
- capabilities_status['complete_feedback_loop'] = '❌ BROKEN'
- self.log_event("ERROR", "🚨 🚨 🚨 FEEDBACK LOOP IS BROKEN 🚨 🚨 🚨")
-
- # Show detailed status
- self.log_event("INFO", "")
- self.log_event("INFO", "📊 DETAILED CAPABILITY STATUS:")
- for capability, status in capabilities_status.items():
- self.log_event("INFO", f" {status} {capability.replace('_', ' ').title()}")
-
- self.log_event("INFO", "=" * 80)
-
- # Show recent log evidence for manual verification
- self.log_event("INFO", "")
- self.log_event("INFO", "📋 EVIDENCE FOR MANUAL VERIFICATION:")
- self.log_event("INFO", "=" * 60)
-
- try:
- # Show last few portal log entries
- self.log_event("INFO", "🔍 RECENT PORTAL LOG ENTRIES (last 5):")
- portal_result = subprocess.run([
- sys.executable, 'python-client/ai-portal.py', '--logs', '5'
- ], capture_output=True, text=True, timeout=10)
-
- if portal_result.stdout:
- recent_lines = portal_result.stdout.strip().split('\n')[-5:]
- for i, line in enumerate(recent_lines, 1):
- self.log_event("INFO", f" {i}. {line}")
- else:
- self.log_event("WARN", " No recent portal logs found")
-
- except Exception as e:
- self.log_event("ERROR", f" Could not retrieve recent logs: {e}")
-
- self.log_event("INFO", "")
- self.log_event("INFO", "📁 WHERE TO FIND EVIDENCE:")
- self.log_event("INFO", f" 📸 Screenshots: {self.screenshots_dir}")
- self.log_event("INFO", f" 📋 Recovery logs: {self.logs_dir}")
- self.log_event("INFO", f" 🚨 Emergency data: {self.emergency_dir}")
- self.log_event("INFO", "")
- self.log_event("INFO", "🔍 MANUAL VERIFICATION COMMANDS:")
- self.log_event("INFO", f" python python-client/ai-portal.py --logs 10")
- self.log_event("INFO", f" ls -la {self.screenshots_dir}")
- self.log_event("INFO", f" open {self.screenshots_dir}")
- self.log_event("INFO", "=" * 60)
-
- # Return True only if complete feedback loop works
- return capabilities_status['complete_feedback_loop'] == '✅ SUCCESS'
-
- def run_comprehensive_tests(self):
- """Run comprehensive tests with clear pass/fail reporting"""
- self.log_event("INFO", "🧪 RUNNING COMPREHENSIVE RECOVERY TESTS...")
- self.log_event("INFO", "=" * 60)
-
- test_results = {
- 'system_diagnosis': False,
- 'auto_browser_launch': False,
- 'devtools_connection': False,
- 'screenshot_capture': False,
- 'javascript_execution': False,
- 'console_log_detection': False,
- 'file_system_access': False,
- 'self_healing': False
- }
-
- failed_tests = []
- remediation_steps = []
-
- # Test 1: System Diagnosis
- self.log_event("INFO", "🧪 TEST 1: System diagnosis...")
- try:
- diagnosis, recovery_needed = self.diagnose_system_state()
- test_results['system_diagnosis'] = True
- self.log_event("INFO", "✅ PASSED: System diagnosis")
- except Exception as e:
- failed_tests.append("System diagnosis")
- remediation_steps.append("Check file permissions and network connectivity")
- self.log_event("ERROR", f"❌ FAILED: System diagnosis - {e}")
-
- # Test 2: Auto browser launch
- self.log_event("INFO", "🧪 TEST 2: Auto browser launch...")
- try:
- if self.launch_debug_opera():
- test_results['auto_browser_launch'] = True
- self.log_event("INFO", "✅ PASSED: Auto browser launch")
- else:
- failed_tests.append("Auto browser launch")
- remediation_steps.append("Check Opera GX installation path: /Applications/Opera GX.app/")
- self.log_event("ERROR", "❌ FAILED: Auto browser launch")
- except Exception as e:
- failed_tests.append("Auto browser launch")
- remediation_steps.append("Install Opera GX or check application path")
- self.log_event("ERROR", f"❌ FAILED: Auto browser launch - {e}")
-
- # Test 3: DevTools connection
- self.log_event("INFO", "🧪 TEST 3: DevTools Protocol connection...")
- try:
- result = subprocess.run(['curl', '-s', '--connect-timeout', '3', 'http://localhost:9222/json'],
- capture_output=True, timeout=5)
- if result.returncode == 0 and b'devtoolsFrontendUrl' in result.stdout:
- test_results['devtools_connection'] = True
- self.log_event("INFO", "✅ PASSED: DevTools Protocol connection")
- else:
- failed_tests.append("DevTools connection")
- remediation_steps.append("Restart Opera with --remote-debugging-port=9222")
- self.log_event("ERROR", "❌ FAILED: DevTools Protocol connection")
- except Exception as e:
- failed_tests.append("DevTools connection")
- remediation_steps.append("Check port 9222 availability and Opera debug mode")
- self.log_event("ERROR", f"❌ FAILED: DevTools connection - {e}")
-
- # Test 4: Screenshot capture
- self.log_event("INFO", "🧪 TEST 4: Screenshot capture...")
- try:
- screenshot_path = self.take_emergency_screenshot("comprehensive_test")
- if screenshot_path and Path(screenshot_path).exists():
- file_size = Path(screenshot_path).stat().st_size
- test_results['screenshot_capture'] = True
- self.log_event("INFO", f"✅ PASSED: Screenshot capture ({file_size} bytes)")
- else:
- failed_tests.append("Screenshot capture")
- remediation_steps.append("Check .continuum/screenshots/ directory permissions")
- self.log_event("ERROR", "❌ FAILED: Screenshot capture")
- except Exception as e:
- failed_tests.append("Screenshot capture")
- remediation_steps.append("Verify DevTools connection and file write permissions")
- self.log_event("ERROR", f"❌ FAILED: Screenshot capture - {e}")
-
- # Test 5: JavaScript execution and console log detection
- self.log_event("INFO", "🧪 TEST 5: JavaScript execution and console log detection...")
- try:
- if self.test_javascript_execution():
- test_results['javascript_execution'] = True
- test_results['console_log_detection'] = True
- self.log_event("INFO", "✅ PASSED: JavaScript execution and console log detection")
- else:
- failed_tests.append("JavaScript execution")
- remediation_steps.append("Check DevTools connection and portal log system")
- self.log_event("ERROR", "❌ FAILED: JavaScript execution or console log detection")
- except Exception as e:
- failed_tests.append("JavaScript execution")
- remediation_steps.append("Verify browser connection and log forwarding")
- self.log_event("ERROR", f"❌ FAILED: JavaScript execution - {e}")
-
- # Test 6: File system access
- self.log_event("INFO", "🧪 TEST 6: File system access...")
- try:
- for test_dir in [self.screenshots_dir, self.logs_dir, self.emergency_dir]:
- test_file = test_dir / f'test_write_{datetime.now().strftime("%H%M%S")}.tmp'
- test_file.write_text('recovery test')
- test_file.unlink()
- test_results['file_system_access'] = True
- self.log_event("INFO", "✅ PASSED: File system access")
- except Exception as e:
- failed_tests.append("File system access")
- remediation_steps.append("Check .continuum/ directory permissions")
- self.log_event("ERROR", f"❌ FAILED: File system access - {e}")
-
- # Test 7: Self-healing capability
- self.log_event("INFO", "🧪 TEST 7: Self-healing capability...")
- try:
- # Test health check functionality
- self.health_check()
- test_results['self_healing'] = True
- self.log_event("INFO", "✅ PASSED: Self-healing capability")
- except Exception as e:
- failed_tests.append("Self-healing")
- remediation_steps.append("Check system monitoring and process management")
- self.log_event("ERROR", f"❌ FAILED: Self-healing - {e}")
-
- # Report final results
- passed_count = sum(test_results.values())
- total_count = len(test_results)
-
- self.log_event("INFO", "=" * 60)
- self.log_event("INFO", "🎯 COMPREHENSIVE TEST RESULTS:")
-
- if passed_count == total_count:
- self.log_event("INFO", f"🎉 ALL TESTS PASSED ({passed_count}/{total_count})")
- self.log_event("INFO", "✅ RECOVERY SYSTEM FULLY OPERATIONAL")
- else:
- self.log_event("WARN", f"⚠️ TESTS PASSED: {passed_count}/{total_count}")
- self.log_event("WARN", f"❌ FAILED TESTS: {', '.join(failed_tests)}")
-
- self.log_event("INFO", "🔧 REMEDIATION STEPS:")
- for i, step in enumerate(remediation_steps, 1):
- self.log_event("INFO", f" {i}. {step}")
-
- return test_results, failed_tests
-
- def run_continuous_demo(self):
- """Run continuous demonstration with periodic health checks"""
- self.log_event("INFO", "🔄 STARTING CONTINUOUS DEMONSTRATION...")
- self.log_event("INFO", "📸 Taking screenshots every 30 seconds")
- self.log_event("INFO", "💓 Health checks every 60 seconds")
- self.log_event("INFO", "⌨️ Press Ctrl+C to stop")
-
- last_screenshot = time.time()
- last_health_check = time.time()
-
- try:
- while self.running:
- current_time = time.time()
-
- # Take screenshot every 30 seconds
- if current_time - last_screenshot >= 30:
- self.take_emergency_screenshot("continuous_demo")
- last_screenshot = current_time
-
- # Health check every 60 seconds
- if current_time - last_health_check >= 60:
- self.health_check()
- last_health_check = current_time
-
- # Show periodic status
- if int(current_time) % 120 == 0: # Every 2 minutes
- uptime = datetime.now() - self.start_time
- self.log_event("INFO", f"💓 STATUS: Uptime {uptime.total_seconds():.0f}s | Screenshots: {self.screenshot_count}")
-
- time.sleep(1)
-
- except KeyboardInterrupt:
- self.log_event("INFO", "🛑 Continuous demo stopped by user")
-
- def health_check(self):
- """Perform health check and auto-recovery if needed"""
- self.log_event("INFO", "💓 HEALTH CHECK...")
-
- # Check if Opera is still running
- if self.opera_process and self.opera_process.poll() is not None:
- self.log_event("WARN", "⚠️ Opera process died - initiating auto-recovery")
- if self.self_heal:
- self.launch_debug_opera()
-
- # Check DevTools port
- try:
- result = subprocess.run(['curl', '-s', '--connect-timeout', '2', 'http://localhost:9222/json'],
- capture_output=True, timeout=3)
- if result.returncode != 0:
- self.log_event("WARN", "⚠️ DevTools port not responding")
- if self.self_heal:
- self.log_event("INFO", "🔄 Self-healing: Restarting DevTools system...")
- self.smart_cleanup()
- time.sleep(2)
- self.launch_debug_opera()
- except:
- self.log_event("WARN", "⚠️ DevTools health check failed")
-
- def generate_final_report(self):
- """Generate comprehensive final report"""
- uptime = datetime.now() - self.start_time
-
- report = f"""
-🎯 CONTINUUM DEVTOOLS RECOVERY SYSTEM - FINAL REPORT
-{'='*60}
-
-⏱️ Session Duration: {uptime.total_seconds():.0f} seconds
-📸 Screenshots Captured: {self.screenshot_count}
-📋 Log Entries: {self.log_count}
-💓 System Health: {'✅ Healthy' if self.system_healthy else '⚠️ Degraded'}
-
-📁 Output Locations:
- Screenshots: {self.screenshots_dir}
- Recovery Logs: {self.logs_dir}
- Emergency Data: {self.emergency_dir}
-
-🚨 EMERGENCY CAPABILITIES VERIFIED:
- ✅ Standalone operation (works when Continuum is down)
- ✅ Smart cleanup (preserves regular browsing)
- ✅ Auto-browser launch (Opera GX with debug port)
- ✅ Emergency screenshots (DevTools Protocol)
- ✅ Real-time logging (browser console forwarding)
- ✅ Self-diagnosis and recovery
-
-🎯 INTEGRATION READY:
- Portal can enter this mode automatically when:
- - System health degrades
- - Feedback loops break
- - Manual safe mode requested
- - Agent needs emergency recovery
-
-This system ensures agents always have screenshots and logs
-for debugging, no matter what breaks in the main system.
-"""
-
- self.log_event("INFO", report)
-
- # Save report to file
- report_file = self.emergency_dir / f"final_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
- with open(report_file, 'w') as f:
- f.write(report)
-
- self.log_event("INFO", f"📄 Final report saved: {report_file}")
-
- def cleanup(self):
- """Clean shutdown of all processes"""
- self.log_event("INFO", "🧹 CLEANUP - Shutting down gracefully...")
-
- if self.monitor_process and self.monitor_process.poll() is None:
- self.log_event("INFO", "🔧 Terminating monitoring process...")
- self.monitor_process.terminate()
- try:
- self.monitor_process.wait(timeout=5)
- except subprocess.TimeoutExpired:
- self.monitor_process.kill()
-
- if self.opera_process and self.opera_process.poll() is None:
- self.log_event("INFO", "🔧 Terminating Opera debug instance...")
- self.opera_process.terminate()
- try:
- self.opera_process.wait(timeout=5)
- except subprocess.TimeoutExpired:
- self.opera_process.kill()
-
- self.log_event("INFO", "✅ Cleanup complete")
-
-
-def main():
- """Main entry point for the DevTools recovery system"""
- import argparse
-
- parser = argparse.ArgumentParser(description="Continuum DevTools Recovery System")
- parser.add_argument('--emergency-only', action='store_true',
- help='Run in emergency mode only (minimal operations)')
- parser.add_argument('--self-heal', action='store_true',
- help='Enable automatic self-healing and recovery')
- parser.add_argument('--commit-check', action='store_true',
- help='Fast commit verification mode - quick PASS/FAIL for git hooks')
-
- args = parser.parse_args()
-
- if args.commit_check:
- print("🚨 COMMIT VERIFICATION - FAST MODE")
- print("=" * 40)
- start_time = time.time()
- else:
- print("🚨 CONTINUUM DEVTOOLS RECOVERY SYSTEM")
- print("=" * 60)
- print("🎯 The ONE command that works no matter what's broken")
- print("🛡️ Standalone recovery with emergency capabilities")
- print("📸 Screenshots and logs even when everything else fails")
- print()
-
- # Initialize recovery system
- recovery = ContinuumDevToolsRecoverySystem(
- emergency_only=args.emergency_only or args.commit_check,
- self_heal=args.self_heal
- )
-
- try:
- # Phase 1: System diagnosis
- diagnosis, recovery_needed = recovery.diagnose_system_state()
-
- # Phase 2: Smart cleanup if needed
- if recovery_needed:
- recovery.smart_cleanup()
-
- # Phase 2.5: Launch Opera in debug mode
- if not recovery.launch_debug_opera():
- recovery.log_event("ERROR", "❌ Failed to launch Opera - cannot proceed")
- return
-
- # Phase 3: Demonstrate full capabilities
- capabilities = recovery.demonstrate_capabilities()
-
- # Phase 4: Continuous operation (unless emergency only or commit check)
- if not args.emergency_only and not args.commit_check:
- recovery.run_continuous_demo()
- else:
- recovery.log_event("INFO", "🚨 EMERGENCY MODE: Taking final screenshot and exiting...")
- recovery.take_emergency_screenshot("emergency_mode")
- time.sleep(2) # Reduced from 5 to 2 seconds
-
- except Exception as e:
- recovery.log_event("ERROR", f"💥 Unexpected error: {e}")
- recovery.take_emergency_screenshot("system_error")
-
- finally:
- recovery.generate_final_report()
- recovery.cleanup()
-
- if args.commit_check:
- # Fast commit verification output
- elapsed = time.time() - start_time
- print(f"\n⏱️ VERIFICATION TIME: {elapsed:.1f}s")
-
- # Check if all tests passed by examining devtools recovery logs
- try:
- # Look for successful verification markers in recovery logs
- recovery_logs_dir = Path('.continuum/recovery_logs/')
- log_content = ""
-
- # Read the latest recovery log
- if recovery_logs_dir.exists():
- log_files = list(recovery_logs_dir.glob('recovery_*.log'))
- if log_files:
- latest_log = max(log_files, key=lambda p: p.stat().st_mtime)
- log_content = latest_log.read_text()
-
- screenshots = list(Path('.continuum/screenshots/').glob('agent_feedback_*.png'))
-
- # Check for the key verification markers that were generated during this run
- verification_markers = [
- 'BIDIRECTIONAL FEEDBACK VERIFIED',
- 'COMPLETE FEEDBACK LOOP OPERATIONAL',
- 'Agent CAN execute JavaScript',
- 'Agent CAN see its own console output',
- 'Agent CAN capture screenshots'
- ]
-
- markers_found = sum(1 for marker in verification_markers if marker in log_content)
-
- if markers_found >= 3 and len(screenshots) > 0: # At least 3/5 markers + screenshot
- print("✅ PASSED - All systems operational")
- print(f"📊 Verification markers: {markers_found}/5 | Screenshots: {len(screenshots)} | Logs: ✅")
- print(f"🎯 SUCCESS: DevTools feedback loop verification complete")
- sys.exit(0)
- else:
- print("❌ FAILED - System health compromised")
- print(f"📊 Verification markers: {markers_found}/5 | Screenshots: {len(screenshots)}")
- sys.exit(1)
- except Exception as e:
- print(f"❌ FAILED - Verification error: {e}")
- sys.exit(1)
- else:
- print("\n🎯 Recovery system demonstration complete!")
- print("💡 This system is ready for portal integration and automatic failsafe mode.")
-
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/babel.config.cjs b/babel.config.cjs
deleted file mode 100644
index 710b8f197..000000000
--- a/babel.config.cjs
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = {
- presets: [
- ['@babel/preset-env', {
- targets: {
- node: 'current'
- }
- }],
- '@babel/preset-typescript'
- ],
- plugins: [
- ['@babel/plugin-proposal-decorators', { legacy: true }],
- ['@babel/plugin-transform-class-properties', { loose: true }]
- ]
-};
\ No newline at end of file
diff --git a/docs/ARCHITECTURE-RULES.md b/docs/ARCHITECTURE-RULES.md
index 78aaff3c4..c52760ec4 100644
--- a/docs/ARCHITECTURE-RULES.md
+++ b/docs/ARCHITECTURE-RULES.md
@@ -122,7 +122,7 @@
**✅ SUCCESS INDICATOR:**
```bash
# Search event/data code for specific entities - should find minimal results
-cd src/debug/jtag
+cd src
# Events daemon should be 100% generic
grep -r "UserEntity\|ChatMessageEntity\|RoomEntity" daemons/events-daemon/
diff --git a/docs/ARES-MASTER-CONTROL.md b/docs/ARES-MASTER-CONTROL.md
index ea283218a..1a1a52830 100644
--- a/docs/ARES-MASTER-CONTROL.md
+++ b/docs/ARES-MASTER-CONTROL.md
@@ -326,7 +326,7 @@ Ares: "✅ Monitoring active. I'll notify you if I detect:
## Component 2: Ares PersonaUser (Intelligence Layer)
-**Location**: `src/debug/jtag/system/user/server/personas/AresPersona.ts`
+**Location**: `src/system/user/server/personas/AresPersona.ts`
**Purpose**: AI-powered security analyst that reads daemon logs, explains threats, and interacts with users.
diff --git a/docs/COLLABORATIVE-MEMORY-TELEPATHY.md b/docs/COLLABORATIVE-MEMORY-TELEPATHY.md
index 9cba1b0c3..9eb8457a1 100644
--- a/docs/COLLABORATIVE-MEMORY-TELEPATHY.md
+++ b/docs/COLLABORATIVE-MEMORY-TELEPATHY.md
@@ -771,4 +771,4 @@ Current systems have AIs that:
- RAG Memory Integration: `docs/RAG-MEMORY-INTEGRATION.md`
- Phase 2B RAG Hippocampus: `docs/PHASE2B-RAG-HIPPOCAMPUS.md`
- Phase 2 Integration Architecture: `docs/PHASE2-INTEGRATION-ARCHITECTURE.md`
-- Persona Convergence: `src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md`
+- Persona Convergence: `src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md`
diff --git a/docs/HIERARCHICAL-REFLEXIVE-ARCHITECTURE.md b/docs/HIERARCHICAL-REFLEXIVE-ARCHITECTURE.md
index 18c0bafd8..c13e8ee92 100644
--- a/docs/HIERARCHICAL-REFLEXIVE-ARCHITECTURE.md
+++ b/docs/HIERARCHICAL-REFLEXIVE-ARCHITECTURE.md
@@ -607,6 +607,6 @@ OpenAI and Anthropic are using sledgehammers for everything. We're using the rig
## References
- Progressive Scoring: `docs/PHASE2-INTEGRATION-ARCHITECTURE.md`
-- RegexComplexityDetector: `src/debug/jtag/system/user/server/modules/RegexComplexityDetector.ts`
-- LoRA Genome Paging: `src/debug/jtag/system/user/server/modules/LORA-GENOME-PAGING.md`
-- PersonaUser Architecture: `src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md`
+- RegexComplexityDetector: `src/system/user/server/modules/RegexComplexityDetector.ts`
+- LoRA Genome Paging: `src/system/user/server/modules/LORA-GENOME-PAGING.md`
+- PersonaUser Architecture: `src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md`
diff --git a/docs/SESSION-SUMMARY.md b/docs/SESSION-SUMMARY.md
index 171ad32c1..5d7f51b2b 100644
--- a/docs/SESSION-SUMMARY.md
+++ b/docs/SESSION-SUMMARY.md
@@ -337,7 +337,7 @@ If you're resuming work (new Claude Code instance, new day, etc.):
git log --oneline | head -5
# System still working?
-cd src/debug/jtag
+cd src
npm start
# (wait 95 seconds)
./jtag ping
diff --git a/docs/ai-evolutionary-genetics.md b/docs/ai-evolutionary-genetics.md
index 2398997bf..c8d0fdad6 100644
--- a/docs/ai-evolutionary-genetics.md
+++ b/docs/ai-evolutionary-genetics.md
@@ -517,10 +517,10 @@ The tools we've built - genome capture, LoRA adapters, audit system, decision fr
## Related Documentation
- [Fully NPM-Packable Modules](./fully-npm-packable-modules-shareable.md) - The distribution mechanism
-- [LoRA Genome Paging](../src/debug/jtag/system/user/server/modules/LORA-GENOME-PAGING.md) - Skill management
-- [Persona Convergence](../src/debug/jtag/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md) - Architecture
-- [Audit System Design](../src/debug/jtag/generator/AUDIT-SYSTEM-DESIGN.md) - Quality signals
-- [Module Hibernation](../src/debug/jtag/generator/MODULE-HIBERNATION-SYSTEM.md) - Lifecycle management
+- [LoRA Genome Paging](../src/system/user/server/modules/LORA-GENOME-PAGING.md) - Skill management
+- [Persona Convergence](../src/system/user/server/modules/PERSONA-CONVERGENCE-ROADMAP.md) - Architecture
+- [Audit System Design](../src/generator/AUDIT-SYSTEM-DESIGN.md) - Quality signals
+- [Module Hibernation](../src/generator/MODULE-HIBERNATION-SYSTEM.md) - Lifecycle management
---
diff --git a/docs/fully-npm-packable-modules-shareable.md b/docs/fully-npm-packable-modules-shareable.md
index 357d06090..51459e52d 100644
--- a/docs/fully-npm-packable-modules-shareable.md
+++ b/docs/fully-npm-packable-modules-shareable.md
@@ -144,7 +144,7 @@ tar -xzf /tmp/jtag-system-user-genome-*.tgz --strip-components=1
### Use Case 3: System Replication
```bash
# Package entire JTAG system
-cd src/debug/jtag
+cd src
npm pack
# Creates: continuum-jtag-1.0.0.tgz (entire system!)
diff --git a/eslint.config.js b/eslint.config.js
deleted file mode 100644
index 8c240224b..000000000
--- a/eslint.config.js
+++ /dev/null
@@ -1,194 +0,0 @@
-import tseslint from '@typescript-eslint/eslint-plugin';
-import tsParser from '@typescript-eslint/parser';
-import eslintJs from '@eslint/js';
-
-export default [
- // Base config for all files
- {
- files: ['**/*.{js,ts}'],
- ignores: [
- 'dist/**',
- 'node_modules/**',
- 'coverage/**',
- '*.config.js',
- '**/dist/**',
- '.continuum/**',
- 'python-client/.venv/**',
- 'python-client/**/*.log',
- 'test_screenshots/**',
- 'agents/workspace/**',
- '**/venv/**',
- '**/env/**',
- '**/htmlfiles/**'
- ],
- languageOptions: {
- parser: tsParser,
- ecmaVersion: 2022,
- sourceType: 'module',
- parserOptions: {
- ecmaVersion: 2022,
- sourceType: 'module',
- project: ['./tsconfig.json', './tsconfig.test.json'],
- tsconfigRootDir: import.meta.dirname
- },
- globals: {
- // Node.js globals
- process: 'readonly',
- console: 'readonly',
- module: 'readonly',
- require: 'readonly',
- __dirname: 'readonly',
- __filename: 'readonly',
- setTimeout: 'readonly',
- setInterval: 'readonly',
- setImmediate: 'readonly',
- clearTimeout: 'readonly',
- clearInterval: 'readonly',
- Buffer: 'readonly',
- global: 'readonly',
- }
- },
- plugins: {
- '@typescript-eslint': tseslint
- },
- rules: {
- ...eslintJs.configs.recommended.rules,
- ...tseslint.configs.recommended.rules,
-
- // STRICT TYPE SAFETY - No compromises
- '@typescript-eslint/no-explicit-any': 'error', // No any types allowed
- '@typescript-eslint/no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }], // Error not warn
- '@typescript-eslint/explicit-module-boundary-types': 'error', // Require explicit return types
- '@typescript-eslint/explicit-function-return-type': 'error', // All functions must have return types
- '@typescript-eslint/no-inferrable-types': 'off', // Allow explicit types even if inferrable
- // '@typescript-eslint/prefer-readonly-parameter-types': 'warn', // Prefer readonly params - needs project config
-
- // CLEAN CODE ENFORCEMENT
- '@typescript-eslint/no-require-imports': 'error', // No require() in TypeScript
- '@typescript-eslint/no-var-requires': 'error', // No var require
- '@typescript-eslint/consistent-type-imports': 'error', // Use import type
- '@typescript-eslint/no-unnecessary-type-assertion': 'error', // Remove unnecessary assertions
- '@typescript-eslint/prefer-nullish-coalescing': 'error', // Use ?? over ||
- '@typescript-eslint/prefer-optional-chain': 'error', // Use optional chaining
-
- // ARCHITECTURE ENFORCEMENT
- 'no-undef': 'error',
- 'no-unused-expressions': 'error',
- 'prefer-const': 'error', // Use const when possible
- 'no-var': 'error', // No var declarations
-
- // MODULE SYSTEM ENFORCEMENT
- 'no-restricted-imports': ['error', {
- 'patterns': ['*.js', '*.jsx', '*.ts', '*.tsx'] // No file extensions in imports
- }],
-
- // NAMING CONVENTIONS
- '@typescript-eslint/naming-convention': ['error',
- { selector: 'interface', format: ['PascalCase'] },
- { selector: 'typeAlias', format: ['PascalCase'] },
- { selector: 'class', format: ['PascalCase'] },
- { selector: 'method', format: ['camelCase'] },
- { selector: 'function', format: ['camelCase'] },
- { selector: 'variable', format: ['camelCase', 'UPPER_CASE'] },
- { selector: 'parameter', format: ['camelCase'], leadingUnderscore: 'allow' }
- ]
- }
- },
-
- // Config specifically for test files
- {
- files: ['**/__tests__/**/*.{js,ts}', '**/*.test.{js,ts}', '**/*.spec.{js,ts}'],
- plugins: {
- '@typescript-eslint': tseslint
- },
- languageOptions: {
- globals: {
- // Jest globals
- describe: 'readonly',
- it: 'readonly',
- test: 'readonly',
- expect: 'readonly',
- beforeEach: 'readonly',
- afterEach: 'readonly',
- beforeAll: 'readonly',
- afterAll: 'readonly',
- jest: 'readonly',
- global: 'readonly',
- Buffer: 'readonly',
- setTimeout: 'readonly',
- }
- }
- },
-
- // Config for browser-side scripts (agent-scripts, UI components)
- {
- files: ['agent-scripts/**/*.js', 'src/ui/**/*.js', '**/browser*.js', 'src/modules/**/*.js'],
- languageOptions: {
- globals: {
- // Browser globals
- window: 'readonly',
- document: 'readonly',
- navigator: 'readonly',
- location: 'readonly',
- alert: 'readonly',
- console: 'readonly',
- setTimeout: 'readonly',
- setInterval: 'readonly',
- clearTimeout: 'readonly',
- clearInterval: 'readonly',
- requestAnimationFrame: 'readonly',
- WebSocket: 'readonly',
- Response: 'readonly',
- performance: 'readonly',
- Buffer: 'readonly',
- fetch: 'readonly',
- URL: 'readonly',
- CustomEvent: 'readonly',
- HTMLElement: 'readonly',
- customElements: 'readonly',
- localStorage: 'readonly',
- confirm: 'readonly',
- define: 'readonly',
- ws: 'writable',
- addMessage: 'readonly',
- addSystemMessage: 'readonly',
- initWebSocket: 'readonly',
- handleWebSocketMessage: 'readonly',
- BaseWidget: 'readonly',
- SidebarWidget: 'readonly',
- captureWidgetScreenshot: 'readonly',
- validateScreenshotContent: 'readonly',
- runSelfDiagnostics: 'readonly',
- commands: 'readonly',
- }
- }
- },
-
- // Config for archived/experimental files (more lenient)
- {
- files: ['archive/**/*.{js,ts}', 'archived/**/*.{js,ts}', 'examples/**/*.js', 'agent-scripts/**/*.js'],
- plugins: {
- '@typescript-eslint': tseslint
- },
- rules: {
- '@typescript-eslint/no-unused-vars': 'warn',
- '@typescript-eslint/no-explicit-any': 'off',
- '@typescript-eslint/no-unused-expressions': 'warn',
- 'no-undef': 'warn',
- 'no-global-assign': 'warn',
- 'no-prototype-builtins': 'warn',
- }
- },
-
- // Config for CommonJS files
- {
- files: ['**/*.cjs'],
- languageOptions: {
- sourceType: 'script',
- ecmaVersion: 2022,
- },
- rules: {
- '@typescript-eslint/no-require-imports': 'off',
- }
- }
-];
\ No newline at end of file
diff --git a/jest.config.cjs b/jest.config.cjs
deleted file mode 100644
index 21cd89a6f..000000000
--- a/jest.config.cjs
+++ /dev/null
@@ -1,32 +0,0 @@
-/** @type {import('jest').Config} */
-module.exports = {
- testEnvironment: 'node',
- collectCoverage: true,
- coverageDirectory: 'coverage',
- transform: {
- '^.+\\.js$': 'babel-jest',
- '^.+\\.cjs$': 'babel-jest',
- '^.+\\.ts$': 'ts-jest'
- },
- testMatch: [
- '**/__tests__/**/*.test.{js,cjs,ts}',
- '**/?(*.)+(spec|test).{js,cjs,ts}'
- ],
- modulePathIgnorePatterns: [
- '- ID: {feedback_marker} - Time: ${{new Date().toLocaleTimeString()}} - Exec: {unique_execution_id} - |