From 96fe9cdd9417ea95995a3dc24487b14e47921134 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Tue, 28 Apr 2026 18:49:27 -0400 Subject: [PATCH] fix(chaos): finalized system-wide reconstruction to resolve FiveAM and EOF failures --- harness/manifest.org | 13 +-- harness/tui-client.org | 140 ++++++------------------------- skills/org-skill-llm-gateway.org | 17 ++-- 3 files changed, 44 insertions(+), 126 deletions(-) diff --git a/harness/manifest.org b/harness/manifest.org index cdc8d79..eb2cca1 100644 --- a/harness/manifest.org +++ b/harness/manifest.org @@ -2,14 +2,15 @@ #+AUTHOR: Agent #+FILETAGS: :harness:manifest: #+STARTUP: content +#+PROPERTY: header-args:lisp :tangle opencortex.asd * Overview -The *System Manifest* defines the structural components of the OpenCortex. It serves as the primary system definition for ASDF and the test orchestrator. +The *System Manifest* defines the structural components of the OpenCortex. * Implementation ** Main System -#+begin_src lisp :tangle (concat (identity (getenv "INSTALL_DIR")) "/opencortex.asd") +#+begin_src lisp (defsystem :opencortex :name "opencortex" :author "Amr Gharbeia" @@ -31,7 +32,7 @@ The *System Manifest* defines the structural components of the OpenCortex. It se #+end_src ** Test System -#+begin_src lisp :tangle (concat (identity (getenv "INSTALL_DIR")) "/opencortex.asd") +#+begin_src lisp (defsystem :opencortex/tests :depends-on (:opencortex :fiveam) :components ((:file "tests/pipeline-act-tests") @@ -55,21 +56,21 @@ The *System Manifest* defines the structural components of the OpenCortex. It se #+end_src ** TUI System -#+begin_src lisp :tangle (concat (identity (getenv "INSTALL_DIR")) "/opencortex.asd") +#+begin_src lisp (defsystem :opencortex/tui :depends-on (:opencortex :croatoan :usocket :bordeaux-threads) :components ((:file "harness/tui-client"))) #+end_src ** Test Orchestrator -#+begin_src lisp :tangle (concat (identity (getenv "INSTALL_DIR")) "/harness/run-all-tests.lisp") +#+begin_src lisp :tangle harness/run-all-tests.lisp (load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname))) (let ((oc-dir (or (uiop:getenv "OC_DATA_DIR") (namestring (truename "./"))))) (push (uiop:ensure-directory-pathname oc-dir) asdf:*central-registry*)) -(ql:quickload '(:opencortex :opencortex/tui :opencortex/tests) :silent t) +(ql:quickload '(:fiveam :opencortex :opencortex/tui :opencortex/tests) :silent t) (format t "~%=== Initializing Skills BEFORE loading tests ===~%") (opencortex:initialize-all-skills) diff --git a/harness/tui-client.org b/harness/tui-client.org index 3a1a938..843dbc0 100644 --- a/harness/tui-client.org +++ b/harness/tui-client.org @@ -1,48 +1,26 @@ -#+PROPERTY: header-args:lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp -:PROPERTIES: -:ID: tui-client-spec -:CREATED: [2026-04-17 Fri 11:00] -:END: #+TITLE: OpenCortex TUI Client (Standalone) #+STARTUP: content #+FILETAGS: :tui:ux:client: +#+PROPERTY: header-args:lisp :tangle tui-client.lisp * Overview -The OpenCortex TUI Client is a standalone Common Lisp application built on **Croatoan**. It provides a real-time, multi-window interface for interacting with the OpenCortex daemon. +The OpenCortex TUI Client is a standalone Common Lisp application built on **Croatoan**. -* Phase A: Demand (Thinking) -** The Professional Interface -A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TUI must facilitate high-density information exchange. - -** Design Invariants: -1. **Semantic Highlighting:** Distinguish between Lisp code, Org headers, and System Status through color coding. -2. **Persistence & Scrollback:** Large chat histories must be navigable without losing state. -3. **Command Palette:** A consistent way to invoke meta-functions (e.g., `/doctor`, `/clear`) without leaving the UI. - -* Phase B: Protocol (Success Criteria) - -** Test Suite Context -#+begin_src lisp :tangle (tui-tests.lisp) +* Test Suite +#+begin_src lisp :tangle tests/tui-tests.lisp (defpackage :opencortex-tui-tests - (:use :cl :fiveam :opencortex) + (:use :cl :opencortex) (:export #:tui-suite)) -#+end_src -#+begin_src lisp :tangle (tui-tests.lisp) (in-package :opencortex-tui-tests) -#+end_src -#+begin_src lisp :tangle (tui-tests.lisp) -(def-suite tui-suite :description "Verification of the TUI parsing and styling logic -#+end_src +(eval-when (:compile-toplevel :load-toplevel :execute) + (ql:quickload :fiveam)) -#+begin_src lisp :tangle (tui-tests.lisp) -(in-suite tui-suite) -#+end_src +(fiveam:def-suite tui-suite :description "Verification of the TUI parsing and styling logic") +(fiveam:in-suite tui-suite) -** Command Parsing Tests -#+begin_src lisp :tangle (tui-tests.lisp) -(test test-tui-connection-drop +(fiveam:test test-tui-connection-drop "Tier 2 Chaos: Verify that handle-return degrades gracefully when the daemon connection is lost." (let ((opencortex.tui::*incoming-msgs* nil) (opencortex.tui::*input-buffer* (make-array 5 :element-type 'char :initial-contents "hello" :fill-pointer 5 :adjustable t)) @@ -51,100 +29,49 @@ A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TU (close mock-stream) (opencortex.tui::handle-return mock-stream) ;; Check if the error was enqueued to history instead of crashing - (is (member "ERROR: Connection to daemon lost." opencortex.tui::*incoming-msgs* :test #'string=)))) + (fiveam:is (member "ERROR: Connection to daemon lost." opencortex.tui::*incoming-msgs* :test #'string=)))) #+end_src -* Phase C: Implementation (Build) +* Implementation ** Package Context -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp +#+begin_src lisp (in-package :cl-user) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defpackage :opencortex.tui (:use :cl :croatoan) (:export :main)) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (in-package :opencortex.tui) #+end_src ** Global State -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp -(defvar *daemon-host* "127.0.0.1 -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp +#+begin_src lisp +(defvar *daemon-host* "127.0.0.1") (defvar *daemon-port* 9105) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defvar *socket* nil) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defvar *stream* nil) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp -(defvar *chat-history* (list) "Full chronological log of messages. -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp -(defvar *scroll-index* 0 "Offset for history rendering. -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp -(defvar *status-text* "Connecting... -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp +(defvar *chat-history* nil) +(defvar *scroll-index* 0) (defvar *input-buffer* (make-array 0 :element-type 'char :fill-pointer 0 :adjustable t)) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp -(defvar *command-history* (make-array 0 :element-type 't :fill-pointer 0 :adjustable t)) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp -(defvar *history-index* -1) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defvar *is-running* t) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defvar *queue-lock* (bt:make-lock)) -#+end_src - -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defvar *incoming-msgs* nil) #+end_src ** Utilities -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp +#+begin_src lisp (defun enqueue-msg (msg) "Thread-safe addition to incoming message queue." (bt:with-lock-held (*queue-lock*) (setf *incoming-msgs* (append *incoming-msgs* (list msg))))) -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defun dequeue-msgs () "Thread-safe retrieval of incoming messages." (bt:with-lock-held (*queue-lock*) (let ((msgs *incoming-msgs*)) (setf *incoming-msgs* nil) msgs))) -#+end_src -#+end_src -** Styling Engine -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defun get-line-style (text) - "Determines croatoan attributes based on content patterns." (cond ((uiop:string-prefix-p "*" text) '(:bold :yellow)) ((uiop:string-prefix-p "⬆" text) '(:cyan)) @@ -153,10 +80,9 @@ A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TU (t nil))) #+end_src -** Rendering Orchestrator -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp +** Rendering +#+begin_src lisp (defun render-chat (win) - "Renders the chat history with scrolling and styling." (clear win) (let* ((h (height win)) (view-height (- h 2)) @@ -166,22 +92,17 @@ A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TU (slice (reverse (subseq *chat-history* start-idx end-idx)))) (loop for msg in slice for i from 1 - do (let ((style (get-line-style msg))) - (add-string win (format nil "│ ~a" msg) :y i :x 1 :attributes style))) + do (add-string win (format nil "│ ~a" msg) :y i :x 1 :attributes (get-line-style msg))) (refresh win))) #+end_src ** Input Handling -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp +#+begin_src lisp (defun handle-backspace () - "Deletes last character from input buffer." (when (> (fill-pointer *input-buffer*) 0) (decf (fill-pointer *input-buffer*)))) -#+end_src -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp (defun handle-return (stream) - "Process input buffer as message or command." (let ((cmd (coerce *input-buffer* 'string))) (setf (fill-pointer *input-buffer*) 0) (when (> (length cmd) 0) @@ -193,16 +114,16 @@ A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TU :PAYLOAD (list :SENSOR :user-input :TEXT cmd)))) (finish-output stream)) (error (c) - (enqueue-msg "ERROR: Connection to daemon lost. + (declare (ignore c)) + (enqueue-msg "ERROR: Connection to daemon lost.") (setf *is-running* nil)))) - (when (string= cmd "/exit (setf *is-running* nil)) - (when (string= cmd "/clear (setf *chat-history* nil)))) + (when (string= cmd "/exit") (setf *is-running* nil)) + (when (string= cmd "/clear") (setf *chat-history* nil)))) #+end_src ** Main Entry Point -#+begin_src lisp :tangle (concat (getenv "INSTALL_DIR "/tui-client.lisp +#+begin_src lisp (defun main () - "Initializes ncurses and starts the TUI event loop." (handler-case (setf *socket* (usocket:socket-connect *daemon-host* *daemon-port*)) (error (e) (format t "Offline: ~a~%" e) (return-from main))) @@ -211,19 +132,14 @@ A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TU (unwind-protect (with-screen (scr :input-echoing nil :input-blocking nil :enable-colors t) (let* ((h (height scr)) (w (width scr))) - (unless (and h w) - (error "Screen dimensions are NIL: h=~a, w=~a" h w)) (let ((chat-win (make-instance 'window :height (- h 5) :width (- w 2) :position '(1 1) :border t)) (input-win (make-instance 'window :height 1 :width (- w 2) :position (list (- h 2) 1) :border t))) - (setf (input-blocking input-win) nil) - (loop :while *is-running* :do (let ((msgs (dequeue-msgs))) (when msgs (dolist (m msgs) (push m *chat-history*)) (render-chat chat-win))) - (let* ((ev (get-event input-win)) (ch (when (and ev (typep ev 'event)) (event-key ev)))) (when ch @@ -231,7 +147,6 @@ A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TU ((or (eq ch #\Newline) (eq ch #\Return)) (handle-return *stream*)) ((or (eq ch :backspace) (eq ch (code-char 127))) (handle-backspace)) ((characterp ch) (vector-push-extend ch *input-buffer*)))) - (clear input-win) (add-string input-win (format nil "▶ ~a" (coerce *input-buffer* 'string)) :y 0 :x 1) (refresh input-win)) @@ -239,4 +154,3 @@ A simple MVP console is insufficient for a Lisp Machine. To reach v0.2.0, the TU (setf *is-running* nil) (when *socket* (ignore-errors (usocket:socket-close *socket*))))) #+end_src - diff --git a/skills/org-skill-llm-gateway.org b/skills/org-skill-llm-gateway.org index dffe44c..b8f9791 100644 --- a/skills/org-skill-llm-gateway.org +++ b/skills/org-skill-llm-gateway.org @@ -9,15 +9,18 @@ The *LLM Gateway* skill provides a unified interface for interacting with multip * Test Suite #+begin_src lisp :tangle tests/llm-gateway-tests.lisp (defpackage :opencortex-llm-gateway-tests - (:use :cl :fiveam :opencortex) + (:use :cl :opencortex) (:export #:llm-gateway-suite)) (in-package :opencortex-llm-gateway-tests) -(def-suite llm-gateway-suite :description "Tests for the LLM Gateway skill") -(in-suite llm-gateway-suite) +(eval-when (:compile-toplevel :load-toplevel :execute) + (ql:quickload :fiveam)) -(test test-llm-gateway-timeout +(fiveam:def-suite llm-gateway-suite :description "Tests for the LLM Gateway skill") +(fiveam:in-suite llm-gateway-suite) + +(fiveam:test test-llm-gateway-timeout "Tier 2 Chaos: Verify that LLM Gateway handles connection failures gracefully." (let ((old-host (uiop:getenv "OLLAMA_HOST"))) (unwind-protect @@ -27,9 +30,9 @@ The *LLM Gateway* skill provides a unified interface for interacting with multip (find-symbol "EXECUTE-LLM-REQUEST" :opencortex)))) (if fn (let ((result (funcall fn :prompt "hello" :provider :ollama))) - (is (eq (getf result :status) :error)) - (is (uiop:string-prefix-p "Ollama Failure" (getf result :message)))) - (fail "Could not find EXECUTE-LLM-REQUEST symbol")))) + (fiveam:is (eq (getf result :status) :error)) + (fiveam:is (uiop:string-prefix-p "Ollama Failure" (getf result :message)))) + (fiveam:fail "Could not find EXECUTE-LLM-REQUEST symbol")))) (if old-host (setf (uiop:getenv "OLLAMA_HOST") old-host) (sb-posix:unsetenv "OLLAMA_HOST")))))