diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index adfd158..0000000 --- a/Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -FROM debian:bullseye-slim - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y \ - sbcl \ - emacs-nox \ - curl \ - git \ - socat \ - netcat-openbsd \ - libssl-dev \ - libncurses5-dev \ - libffi-dev \ - zlib1g-dev \ - libsqlite3-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install Quicklisp -RUN curl -O https://beta.quicklisp.org/quicklisp.lisp \ - && sbcl --non-interactive --load quicklisp.lisp --eval "(quicklisp-quickstart:install)" --eval "(ql-util:without-prompting (ql:add-to-init-file))" \ - && rm quicklisp.lisp - -WORKDIR /app -COPY . . - -# Initialize system in non-interactive mode -RUN mkdir -p /root/memex /app/environment/logs && ./opencortex.sh setup --non-interactive - -EXPOSE 9105 - -CMD ["./opencortex.sh", "boot"] diff --git a/docs/MVP_SPEC.org b/docs/MVP_SPEC.org deleted file mode 100644 index 581f299..0000000 --- a/docs/MVP_SPEC.org +++ /dev/null @@ -1,93 +0,0 @@ -#+TITLE: OpenCortex MVP (v0.1.0) Specification & Release Plan -#+STARTUP: content - -* Objective -Define detailed specifications for the OpenCortex MVP (v0.1.0). This MVP establishes the autonomous foundation and introduces a native Common Lisp Terminal User Interface (TUI) for improved UX, alongside a comprehensive release plan. - -* 1. Core Architecture & Environment (Completed) -- *System Harness:* A minimal, un-brittle Common Lisp (SBCL) microkernel that orchestrates the Perceive -> Probabilistic -> Deterministic -> Dispatch pipeline. -- *Dual-Engine Cognition:* - - /Probabilistic Engine:/ The LLM gateway handling semantic translation, multi-modal ingestion, and intent parsing (supporting Anthropic, Gemini, Groq, OpenAI, and Ollama). - - /Deterministic Engine:/ The Lisp logical core that mathematically verifies LLM-proposed actions against system rules prior to execution. -- *Data Stores:* - - /Linguistic Substrate:/ Org-mode plaintext files acting as the universal Abstract Syntax Tree (AST) for both humans and the agent. - - /Lisp Memory:/ A live, threaded graph of Lisp objects representing the Memex in RAM for instant, token-efficient traversal (Sparse Trees). -- *Skill Architecture:* All agent capabilities are encapsulated in single-file Literate Programs (~org-skill-*.org~). They are topologically loaded, dynamically compiled, and hot-reloadable. - -* 2. Mandatory Security & Containment (Completed) -- *Formal Verification Gate:* Evaluates actions before they hit the OS. - - /Path Confinement:/ Guarantees file writes are physically locked to the `~/memex/` root directory. - - /Network Exfiltration:/ Intercepts and blocks unauthorized external generic HTTP or socket requests. -- *System Policy Gate:* Enforces the "Zero-Bloat" and "Autonomy Above All" invariants. -- *Credentials Vault:* API keys and ~.env~ files are stored in a secure, masked Lisp enclave, rendering them invisible to the LLM's context window. - -* 3. Autonomous Background Workers (Completed) -- *The Scribe (~org-skill-scribe.org~):* A distillation engine that periodically reads the chronological logs (e.g., daily journal files) and autonomously extracts concepts into permanent Zettelkasten notes. -- *The Gardener (~org-skill-gardener.org~):* A heartbeat-driven, idle process that continuously walks the memory graph. It automatically repairs broken internal links, infers missing metadata, and flags orphaned ideas for the user. - -* 4. Native Terminal User Interface (UX Target) -- *Objective:* Eliminate raw ~stdout~ shell piping in favor of a rich, structured, and interactive Common Lisp TUI. -- *Library:* ~croatoan~ (A high-level CLOS wrapper for ncurses) will be used for rapid, robust UI development. -- *Layout:* - - /Main Viewport:/ A read-only, scrollable panel that renders Org-mode headlines, syntax-highlighted Lisp/Python code blocks, and system logs. - - /Input Box:/ A fixed, multi-line input area pinned to the bottom of the screen, supporting standard Readline keybindings. - - /Status Bar:/ A persistent bar at the top or bottom displaying the health and current activity of background workers (Scribe/Gardener) and memory usage. -- *Interactive Control (Slash Commands):* - - ~/help~: View system overview and command syntax. - - ~/clear~: Clear the viewport buffer. - - ~/skill-load ~: Dynamically reload a modified Lisp skill into the active image. - - ~/exit~: Gracefully shut down the harness and exit the environment. - - ~/status~: Print diagnostic report (memory, git status, worker uptimes). - - ~/config~: Display active config/env vars (masking secrets). - - ~/search ~: Raw deterministic regex/vector search across the Memex. - - ~/commit~: Trigger Engineering Standard check, stage, and commit Memex state. -- *Refactoring:* Reroute the existing ~:cli~ actuator and inbound gateway to exclusively utilize the new TUI rendering engine. - -* 5. Release & Publication Plan (v0.1.0) -- *Documentation:* - - ~USER_MANUAL.md~: A comprehensive guide on the one-liner installation (~opencortex.sh~), daily workflow, and navigating the Memex directory structure. - - ~CONTRIBUTING.md~: A guide to "Literate Granularity" engineering standards and creating new ~org-skill-*.org~ files. -- *Legal Finalization:* - - Assign the *AGPLv3* open-source license. - - Implement a broad *Contributor License Agreement (CLA)* process for external contributors to license rights back to the core project. - - Update ~LICENSE~ and finalize ~CHANGELOG.org~. -- *End-to-End Walkthrough:* Execute a clean-slate test of the installation script, boot sequence, environment variable parsing, and autonomous background worker triggers. -- *Marketing & Launch:* Migrate the canonical repository to GitHub (configure topics, badges, and issue templates). Record a high-fidelity GIF/video of the new TUI interaction and execute announcements on Hacker News, Reddit, and X/Twitter. - -* 6. User-Centric End-to-End Test Plan - -This section defines the precise workflow and expected user experience for the v0.1.0 MVP. It serves as the definitive manual testing script before release. - -** Phase 1: The One-Liner Installation & Boot -- *Action:* The user executes the canonical curl-bash script: ~curl -fsSL https://raw.githubusercontent.com/gharbeia/opencortex/main/opencortex.sh | bash~ -- *Expected Experience:* - 1. The script detects the OS and installs any missing system dependencies (e.g., Docker, SBCL, Quicklisp). - 2. It interactively prompts the user to enter as many LLM API keys as they choose to (e.g., Gemini, Anthropic, OpenAI). The user can skip this step and configure them later. - 3. It asks the user for their existing folder structure and fills in the corresponding values (INBOX_DIR, DAILY_DIR, etc.) in ~.env.example~ to generate a valid ~.env~ file. - 4. It compiles and launches the ~opencortex-server~ daemon in the background. - 5. The user is greeted with a success message instructing them to run ~opencortex tui~. - -** Phase 2: First Contact (The TUI Experience) -- *Action:* The user types ~opencortex tui~ in their terminal. -- *Expected Experience:* - 1. The terminal clears and launches the Croatoan UI. - 2. The *Status Bar* appears at the bottom, indicating: ~[Scribe: Idle] [Gardener: Sleeping]~. - 3. The user types a natural language message in the input box: "Hello, what is my current Memex structure?" and presses Enter. - 4. The input box clears, and the user's message appears in the main viewport. - 5. A few seconds later, the agent responds with a formatted Org-mode list of the directories, demonstrating successful Lisp s-expression communication over the TCP socket and valid probabilistic reasoning. - -** Phase 3: The Autonomous Subroutines -- *Action:* The user creates a messy text file in ~/memex/daily/YYYY-MM-DD.org~ with a scattered thought about a new project, then waits. -- *Expected Experience:* - 1. Without any user prompting, the *Status Bar* updates to ~[Scribe: Distilling...]~. - 2. A quiet log message appears in the TUI viewport: ~*System*: Scribe extracted 1 new Zettelkasten note.~ - 3. The user inspects ~/memex/notes/~ and finds a cleanly formatted, semantically tagged Org node containing the distilled thought. - 4. The user intentionally breaks an Org-roam link in one of their notes. Minutes later, the Gardener awakens (~[Gardener: Auditing]~), and a log message appears indicating the link was repaired or flagged. - -** Phase 4: Deterministic Actuation (Slash Commands) -- *Action:* The user types ~/status~ in the TUI. -- *Expected Experience:* The TUI instantly prints a diagnostic report showing memory usage, uptime, and git status, bypassing the LLM entirely. -- *Action:* The user types ~/commit~. -- *Expected Experience:* The system runs the Engineering Standard gate, stages all changes in ~/memex~, and creates a git commit. The TUI confirms success. -- *Action:* The user types ~/exit~. -- *Expected Experience:* The TUI client gracefully disconnects and closes, returning the user to their standard bash prompt. The ~opencortex-server~ continues running safely in the background. diff --git a/docs/marketing-v0.1.0.org b/docs/marketing-v0.1.0.org deleted file mode 100644 index 85466cc..0000000 --- a/docs/marketing-v0.1.0.org +++ /dev/null @@ -1,46 +0,0 @@ -#+TITLE: v0.1.0 Launch & Marketing Plan -#+AUTHOR: Amr -#+FILETAGS: :marketing:release:autonomy: -#+STARTUP: content - -* Overview -With the v0.1.0 "Autonomous MVP" released, the goal is to leverage GitHub's social graph to build a community of early adopters, contributors, and power users who resonate with the "Thin Harness, Fat Skills" and "Local-First" philosophy. - -* 1. Licensing Strategy -Before wide promotion, the project's license must align with its goals. -- **MIT License (Current):** Maximum adoption, frictionless for developers to embed in their own tools. Good for rapid growth. -- **GPLv3 / AGPLv3:** Enforces copyleft. Ensures any modifications or integrations by corporations must remain open-source. Protects the "Autonomous" ethos from proprietary enclosure. -- **Dual Licensing:** Open-source for individuals, commercial license for enterprise usage (if monetization is a future goal). - -*Decision Needed:* Do we stick with MIT, or switch to a copyleft license (AGPL) to protect the autonomous nature of the project? - -* 2. The GitHub Migration & Setup -To maximize visibility, the repository must be optimized for GitHub's ecosystem. -- [ ] **Mirror/Migrate to GitHub:** Move the primary remote from the self-hosted Gitea to GitHub. -- [ ] **README Optimization:** Add badges (License, Build Status, Version). Ensure the "Zero-to-One" curl command is prominent. Add an architecture diagram (mermaid). -- [ ] **Repository Topics:** Add tags like `common-lisp`, `autonomous-agents`, `org-mode`, `pkm`, `zettelkasten`, `llm`, `local-first`. -- [ ] **Contributing Guide:** Add `CONTRIBUTING.md` to explain the Literate Programming standard and how to add new "Skills". -- [ ] **Issue Templates:** Create templates for "Bug Report" and "Skill Proposal". - -* 3. The PR & Social Media Campaign -The narrative: "An autonomous AI agent that doesn't just chat, but lives natively in your Org-mode Memex. No Python glue code, no cloud lock-in—just pure, homoiconic Common Lisp." - -** Target Audiences & Channels -1. **The Emacs / Org-mode Community:** - - *Channels:* `r/emacs`, `r/orgmode`, Hacker News (`/r/lisp`), Emacs News. - - *Hook:* "A background daemon that autonomously distills your daily logs into a Zettelkasten using LLMs." -2. **The Local-First / PKM Community:** - - *Channels:* `r/Zettelkasten`, `r/PKM`, Obsidian/Logseq diaspora looking for more power. - - *Hook:* "Own your brain. An AI agent that runs locally on your Markdown/Org files with mathematical security gates." -3. **The AI / Autonomous Agent Hackers:** - - *Channels:* Hacker News (Show HN), Twitter/X (AI tech Twitter). - - *Hook:* "Tired of fragile Python/Playwright agent wrappers? opencortex uses a deterministic Lisp microkernel to formally verify LLM actions before execution." - -** Launch Materials -- **Demo Video (2 minutes):** Show the one-liner install, the agent running the `Scribe` skill in the background, and the user querying it via `opencortex chat`. -- **Blog Post / Essay:** "Why we built an Autonomous Agent in Common Lisp." Discuss the fragility of current SOTA (Devin/SWE-agent) and the necessity of the Bouncer/Policy gates. - -* 4. Post-Launch Community Engagement -- Encourage "Show and Tell" in GitHub Discussions. -- Create a "Skill Directory" where users can share their custom `.org` skills. -- Actively solicit feedback for the v0.2.0 (Lisp TUI) roadmap. diff --git a/docs/ux.org b/docs/ux.org deleted file mode 100644 index eb64c02..0000000 --- a/docs/ux.org +++ /dev/null @@ -1,66 +0,0 @@ -#+TITLE: User Experience (UX) Journey -#+AUTHOR: Amr -#+FILETAGS: :ux:design:autonomy: -#+STARTUP: content - -* Overview -This document traces the intended User Experience (UX) journey for the ~opencortex~. It serves as a living design document to ensure that architectural decisions align with a frictionless, autonomous, and intuitive user interaction model. - -* 1. The Zero-to-One Experience (Onboarding) -** Goal -A user should be able to go from discovering the project to having a running, calibrated agent in under 3 minutes, with zero prerequisite knowledge of Lisp. - -** The Appliance Paradigm (Primary Path) -The user runs a single command in their terminal: -#+begin_src bash -curl -fsSL https://raw.githubusercontent.com/gharbeia/opencortex/main/scripts/install.sh | bash -#+end_src - -** The Interactive Wizard -The script verifies Docker presence and then launches an interactive prompt before booting the container: -1. *Identity:* "What is your name?" -> Configures ~$MEMEX_USER~ -2. *Assistant:* "What shall we name your Assistant?" -> Configures ~$MEMEX_ASSISTANT~ -3. *Neural Provider:* "Select your primary neural provider [Gemini/OpenRouter/Anthropic/OpenAI]" -> Configures API Keys. -4. *Data Gravity:* "Where is your Memex located?" -> Maps the host directory to the Docker container. - -*Outcome:* The `.env` is generated, core skills are seeded into the user's Memex, and `docker-compose up -d` launches the daemon in the background. The user sees: /"Booting your autonomous brain in the background..."/ - -* 2. The First Contact (The CLI Gateway) -** Goal -Immediately after boot, the user needs a way to verify the agent is alive and capable of answering questions about their Memex without configuring complex third-party integrations (like Telegram bots). - -** The Interaction -The user types a local client command to connect to the background daemon: -#+begin_src bash -opencortex chat -#+end_src - -This opens a slick, colorful interactive terminal session: -#+begin_example -> User: Hello, what are my active projects? -> Agent: [Thinking...] -> Agent: You currently have 3 active projects: -> 1. OpenCortex v1.0 -> 2. Home Renovation -> 3. Read 'The Autonomous Individual' -#+end_example - -** Behind the Scenes -1. The ~opencortex chat~ client connects to the daemon's local port (e.g., 9105). -2. It sends a ~:chat-message~ signal. -3. The core harness routes this to the Probabilistic Engine. -4. The Context Manager retrieves active projects from the Memex AST. -5. The Deterministic Engine (Bouncer) verifies it is a safe read-only action. -6. The ~:cli~ Actuator formats the Lisp response into Markdown and sends it back over the socket. - -* 3. The Interactive Refinement (v0.2.0) -** Goal -Transition from a "Verified Wrapper" around netcat to a high-fidelity, native Common Lisp TUI that rivals the experience of ~gemini-cli~. - -** Features -- *Homoiconic UI:* The TUI is rendered directly by the Lisp kernel, allowing for live introspection of the agent's thoughts. -- *Rich Formatting:* ANSI colors, bold headers, and syntax-highlighted code blocks. -- *Command Palette:* Slash commands for system control without leaving the chat. - -* 4. The Continuous Loop (Daily Usage) -(To be defined as the agent's capabilities expand into Scribe, Gardener, and Emacs-native interactions). diff --git a/infrastructure/docker/Dockerfile b/infrastructure/docker/Dockerfile index 6e35d6b..adfd158 100644 --- a/infrastructure/docker/Dockerfile +++ b/infrastructure/docker/Dockerfile @@ -1,44 +1,32 @@ -FROM debian:bookworm-slim +FROM debian:bullseye-slim -# Install SBCL, ripgrep, and build dependencies -RUN apt-get update && \ - apt-get install -y sbcl build-essential curl git ripgrep libsqlite3-dev lynx python3 python3-pip && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* +ENV DEBIAN_FRONTEND=noninteractive -# Install Quicklisp globally -RUN curl -O https://beta.quicklisp.org/quicklisp.lisp && \ - sbcl --non-interactive \ - --load quicklisp.lisp \ - --eval '(quicklisp-quickstart:install :path "/opt/quicklisp")' \ - --eval '(ql-util:without-prompting (ql:add-to-init-file))' && \ - rm quicklisp.lisp +RUN apt-get update && apt-get install -y \ + sbcl \ + emacs-nox \ + curl \ + git \ + socat \ + netcat-openbsd \ + libssl-dev \ + libncurses5-dev \ + libffi-dev \ + zlib1g-dev \ + libsqlite3-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install Quicklisp +RUN curl -O https://beta.quicklisp.org/quicklisp.lisp \ + && sbcl --non-interactive --load quicklisp.lisp --eval "(quicklisp-quickstart:install)" --eval "(ql-util:without-prompting (ql:add-to-init-file))" \ + && rm quicklisp.lisp -# Set up the working directory WORKDIR /app +COPY . . -# Copy source code and system definition -COPY opencortex.asd /app/ -COPY src/ /app/src/ +# Initialize system in non-interactive mode +RUN mkdir -p /root/memex /app/environment/logs && ./opencortex.sh setup --non-interactive -# Ensure we aren't using a stale binary from the host -RUN rm -f /app/opencortex-server +EXPOSE 9105 -# Build the standalone binary natively inside the container -# This ensures GLIBC compatibility with the runtime environment. -RUN sbcl --non-interactive \ - --eval '(push "/app/" asdf:*central-registry*)' \ - --eval '(ql:quickload :opencortex)' \ - --eval '(asdf:make :opencortex)' - -# Ensure the binary is executable -RUN chmod +x /app/opencortex-server - -# Expose the communication protocol and Web Dashboard ports -EXPOSE 9105 8080 - -# The app expects the memex to be mounted here -VOLUME /memex - -# Run the natively compiled standalone daemon -CMD ["./opencortex-server"] +CMD ["./opencortex.sh", "boot"] diff --git a/infrastructure/guix/manifest.scm b/infrastructure/guix/manifest.scm deleted file mode 100644 index a4e8528..0000000 --- a/infrastructure/guix/manifest.scm +++ /dev/null @@ -1,14 +0,0 @@ -;; opencortex: Guix Environment Manifest -;; Usage: guix shell -m manifest.scm -- sbcl --eval ... - -(specifications->manifest - '("sbcl" - "sbcl-cl-json" - "sbcl-bordeaux-threads" - "sbcl-usocket" - "sbcl-dexador" - "sbcl-cl-ppcre" - "ripgrep" - "git" - "curl" - "sqlite")) diff --git a/infrastructure/lxc/setup.org b/infrastructure/lxc/setup.org deleted file mode 100644 index e4b4a1e..0000000 --- a/infrastructure/lxc/setup.org +++ /dev/null @@ -1,33 +0,0 @@ -#+TITLE: LXC / Systemd-nspawn Deployment Guide -#+AUTHOR: opencortex - -* Overview -For users who prefer containerization without the overhead or dependency on the Docker daemon, `opencortex` can be run within a standard Linux Container (LXC) or a systemd-nspawn container. - -* Systemd-nspawn Setup (Fastest for Linux users) - -1. **Create the container root:** - #+begin_src bash - sudo debootstrap --arch=amd64 bookworm /var/lib/machines/opencortex - #+end_src - -2. **Start and enter the container:** - #+begin_src bash - sudo systemd-nspawn -D /var/lib/machines/opencortex - #+end_src - -3. **Install dependencies (inside container):** - #+begin_src bash - apt-get update && apt-get install -y sbcl curl git ripgrep libsqlite3-dev build-essential - #+end_src - -4. **Bind mount the Memex directory:** - Add this to your container startup or use the `--bind` flag: - #+begin_src bash - sudo systemd-nspawn -D /var/lib/machines/opencortex --bind /home/amr/.openclaw/workspace/memex - #+end_src - -* Proxmox LXC Setup -1. Create a new LXC container using the Debian 12 template. -2. Ensure the network is bridged so Emacs can reach it. -3. Run the `deploy/bare-metal/install.sh` script inside the container. diff --git a/infrastructure/vms/debian/Vagrantfile b/infrastructure/vms/debian/Vagrantfile deleted file mode 100644 index 102d3e4..0000000 --- a/infrastructure/vms/debian/Vagrantfile +++ /dev/null @@ -1,22 +0,0 @@ -Vagrant.configure("2") do |config| - config.vm.box = "debian/bookworm64" - config.vm.network "forwarded_port", guest: 9105, host: 9105 - - config.vm.provider "virtualbox" do |vb| - vb.memory = "1024" - vb.cpus = 2 - end - - config.vm.provision "shell", inline: <<-SHELL - apt-get update - apt-get install -y sbcl curl git ripgrep libsqlite3-dev build-essential - - # Setup for opencortex - mkdir -p /home/vagrant/opencortex - cp -r /vagrant/* /home/vagrant/opencortex/ - chown -R vagrant:vagrant /home/vagrant/opencortex - - # Build binary natively - sudo -u vagrant bash -c "cd /home/vagrant/opencortex && ./deploy/bare-metal/install.sh" - SHELL -end diff --git a/infrastructure/vms/fedora/Vagrantfile b/infrastructure/vms/fedora/Vagrantfile deleted file mode 100644 index f0f5a70..0000000 --- a/infrastructure/vms/fedora/Vagrantfile +++ /dev/null @@ -1,21 +0,0 @@ -Vagrant.configure("2") do |config| - config.vm.box = "fedora/39-cloud-base" - config.vm.network "forwarded_port", guest: 9105, host: 9105 - - config.vm.provider "virtualbox" do |vb| - vb.memory = "1024" - vb.cpus = 2 - end - - config.vm.provision "shell", inline: <<-SHELL - dnf install -y sbcl curl git ripgrep sqlite-devel make gcc - - # Setup for opencortex - mkdir -p /home/vagrant/opencortex - cp -r /vagrant/* /home/vagrant/opencortex/ - chown -R vagrant:vagrant /home/vagrant/opencortex - - # Build binary natively - sudo -u vagrant bash -c "cd /home/vagrant/opencortex && ./deploy/bare-metal/install.sh" - SHELL -end diff --git a/interfaces/__pycache__/ui_driver.cpython-313.pyc b/interfaces/__pycache__/ui_driver.cpython-313.pyc deleted file mode 100644 index cbda2ea..0000000 Binary files a/interfaces/__pycache__/ui_driver.cpython-313.pyc and /dev/null differ diff --git a/interfaces/browser-bridge.py b/interfaces/browser-bridge.py deleted file mode 100644 index 9cd0c2c..0000000 --- a/interfaces/browser-bridge.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python3 -import sys -import json -import base64 -from playwright.sync_api import sync_playwright - -def run_bridge(): - # Read command from stdin - try: - raw_input = sys.stdin.read() - if not raw_input: - print(json.dumps({"status": "error", "message": "No input provided"})) - return - - args = json.loads(raw_input) - except Exception as e: - print(json.dumps({"status": "error", "message": f"Invalid JSON input: {str(e)}"})) - return - - url = args.get("url") - action = args.get("action", "extract_text") - selector = args.get("selector", "body") - - if not url: - print(json.dumps({"status": "error", "message": "No URL provided"})) - return - - try: - with sync_playwright() as p: - browser = p.chromium.launch(headless=True) - page = browser.new_page() - - # Navigate and wait for network to be idle - page.goto(url, wait_until="networkidle") - - result = {"status": "success", "url": url} - - if action == "extract_text": - result["content"] = page.inner_text(selector) - elif action == "screenshot": - screenshot_bytes = page.screenshot() - result["screenshot_base64"] = base64.b64encode(screenshot_bytes).decode("utf-8") - else: - result["status"] = "error" - result["message"] = f"Unknown action: {action}" - - browser.close() - print(json.dumps(result)) - - except Exception as e: - print(json.dumps({"status": "error", "message": f"Playwright Error: {str(e)}"})) - -if __name__ == "__main__": - run_bridge() diff --git a/interfaces/ui_driver.py b/interfaces/ui_driver.py deleted file mode 100755 index a0da35d..0000000 --- a/interfaces/ui_driver.py +++ /dev/null @@ -1,85 +0,0 @@ -import pty -import os -import sys -import time -import select -import re - -class VirtualTerminal: - def __init__(self, rows=24, cols=80): - self.rows = rows - self.cols = cols - self.buffer = [[' ' for _ in range(cols)] for _ in range(rows)] - self.cursor_y = 0 - self.cursor_x = 0 - - def _strip_ansi(self, text): - # Very basic ANSI parser for cursor moves and clears - # CSI n ; m H (cursor move) - # CSI J (clear screen) - # CSI K (clear line) - - # This is a simplified state machine - parts = re.split(r'(\x1b\[[0-9;?]*[a-zA-Z])', text) - for part in parts: - if part.startswith('\x1b['): - cmd = part[-1] - params = part[2:-1].split(';') - if cmd == 'H' or cmd == 'f': # Move cursor - self.cursor_y = int(params[0]) - 1 if params[0] else 0 - self.cursor_x = int(params[1]) - 1 if (len(params) > 1 and params[1]) else 0 - elif cmd == 'J': # Clear - mode = int(params[0]) if params[0] else 0 - if mode == 2: # Full clear - self.buffer = [[' ' for _ in range(self.cols)] for _ in range(self.rows)] - elif cmd == 'm': # Attributes - ignore for now - pass - else: - for char in part: - if char == '\n': - self.cursor_y += 1 - self.cursor_x = 0 - elif char == '\r': - self.cursor_x = 0 - elif 0 <= self.cursor_y < self.rows and 0 <= self.cursor_x < self.cols: - self.buffer[self.cursor_y][self.cursor_x] = char - self.cursor_x += 1 - - def get_screen(self): - return "\n".join(["".join(row) for row in self.buffer]) - -def run_test(command, input_sequence, wait_time=5): - pid, fd = pty.fork() - if pid == 0: - os.environ["TERM"] = "xterm" - os.environ["COLUMNS"] = "80" - os.environ["LINES"] = "24" - os.execvp(command[0], command) - else: - vt = VirtualTerminal() - start_time = time.time() - input_sent = False - - while time.time() - start_time < wait_time: - r, w, e = select.select([fd], [], [], 0.1) - if fd in r: - try: - data = os.read(fd, 8192).decode(errors='ignore') - vt._strip_ansi(data) - except OSError: - break - - if not input_sent and time.time() - start_time > 2: - os.write(fd, input_sequence.encode()) - input_sent = True - - os.kill(pid, 9) - os.waitpid(pid, 0) - return vt - -if __name__ == "__main__": - # Example usage: python3 ui_driver.py sbcl --eval ... - vt = run_test(sys.argv[1:], "Hi\r", wait_time=10) - print("--- VIRTUAL SCREEN SNAPSHOT ---") - print(vt.get_screen()) - print(f"--- CURSOR POSITION: ({vt.cursor_y}, {vt.cursor_x}) ---") diff --git a/tests/org-agent-test.el b/tests/opencortex-test.el similarity index 100% rename from tests/org-agent-test.el rename to tests/opencortex-test.el diff --git a/tests/ui_tui_test.py b/tests/ui_tui_test.py deleted file mode 100644 index a705066..0000000 --- a/tests/ui_tui_test.py +++ /dev/null @@ -1,67 +0,0 @@ -import sys -import os -import time - -# Add scripts directory to path to import ui_driver -sys.path.append(os.path.join(os.getcwd(), 'scripts')) -from ui_driver import run_test - - -def wait_for_brain(): - print("[UI TEST] Waiting for Brain to wake up...") - for i in range(60): - if os.path.exists('brain.log'): - with open('brain.log', 'r') as f: - if 'Boot Complete' in f.read(): - print("[UI TEST] Brain is Green. Waiting for TCP listener...") - time.sleep(5) - return True - time.sleep(2) - return False - -def test_tui_boot_and_input(): - if not wait_for_brain(): - print("FAIL: Brain failed to boot within timeout.") - return - - print("[UI TEST] Launching TUI and sending 'Hi'...") - - # We run the TUI script via bash - - # Direct SBCL launch to bypass shell script noise - command = ["sbcl", "--disable-debugger", - "--eval", "(load (merge-pathnames \"quicklisp/setup.lisp\" (user-homedir-pathname)))", - "--eval", "(push (truename \"\") asdf:*central-registry*)", - "--eval", "(ql:quickload :opencortex/tui)", - "--eval", "(opencortex.tui:main)"] - - vt = run_test(command, "Hi\r", wait_time=15) - - screen = vt.get_screen() - - # 1. Verify Prompt - if "> Hi" in screen: - print("PASS: Local Echo found in chat history.") - elif ">" in screen: - print("PASS: Input prompt found.") - else: - print("FAIL: No input prompt found.") - - # 2. Verify Status Bar - if "[Scribe:" in screen and "Gardener:" in screen: - print("PASS: Status bar rendered correctly.") - else: - print("FAIL: Status bar missing.") - - # 3. Verify Cursor Position (should be at the end of the empty prompt after Enter) - # The prompt is line 23 (h-1), col 2 (after "> ") - if vt.cursor_y == 23 and vt.cursor_x == 2: - print(f"PASS: Cursor is correctly pinned to prompt at ({vt.cursor_y}, {vt.cursor_x}).") - else: - print(f"WARN: Cursor at unexpected position ({vt.cursor_y}, {vt.cursor_x}).") - - print("\n--- FINAL SCREEN SNAPSHOT ---") - print(screen) - -if __name__ == "__main__": - test_tui_boot_and_input()