name: Tests on: push: tags: - 'v*' workflow_dispatch: jobs: test: runs-on: ubuntu-latest env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: - uses: actions/checkout@v4 - name: Install system dependencies run: | sudo apt-get update && sudo apt-get install -y --no-install-recommends \ sbcl emacs-nox git curl socat rlwrap - name: Install Quicklisp run: | curl -L https://beta.quicklisp.org/quicklisp.lisp -o /tmp/quicklisp.lisp sbcl --non-interactive \ --load /tmp/quicklisp.lisp \ --eval '(quicklisp-quickstart:install :path "~/quicklisp/")' \ --eval '(ql:add-to-init-file)' - name: Load and verify harness run: | export OC_DATA_DIR="$PWD/.github-test" mkdir -p "$OC_DATA_DIR/harness" "$OC_DATA_DIR/tests" # Tangle harness files into test directory mkdir -p /tmp/oc-build cp harness/*.org "$OC_DATA_DIR/harness/" cd "$OC_DATA_DIR/harness" && for f in *.org; do if command -v emacs; then emacs -Q --batch --eval "(require 'org)" \ --eval "(setq org-confirm-babel-evaluate nil)" \ --eval "(org-babel-tangle-file \"$f\")" 2>/dev/null || true fi done rm -f *.org cd "$OLDPWD" # Copy skills, tangle, verify mkdir -p "$OC_DATA_DIR/skills" cp skills/*.org "$OC_DATA_DIR/skills/" cd "$OC_DATA_DIR/skills" && for f in *.org; do if command -v emacs; then emacs -Q --batch --eval "(require 'org)" \ --eval "(setq org-confirm-babel-evaluate nil)" \ --eval "(org-babel-tangle-file \"$f\")" 2>/dev/null || true fi done rm -f *.org cd "$OLDPWD" - name: Load opencortex and initialize skills run: | export OC_DATA_DIR="$PWD/.github-test" sbcl --non-interactive \ --eval '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \ --eval "(push (truename \"$PWD/\") asdf:*central-registry*)" \ --eval "(push (truename \"$OC_DATA_DIR/\") asdf:*central-registry*)" \ --eval '(ql:quickload :opencortex :silent t)' \ --eval "(setf (uiop:getenv \"OC_DATA_DIR\") \"$OC_DATA_DIR\")" \ --eval '(opencortex:initialize-all-skills)' \ --eval "(let ((n (hash-table-count opencortex:*skills-registry*))) (format t \"~%Skills loaded: ~a~%\" n) (unless (>= n 20) (sb-ext:exit :code 1)))" - name: Daemon smoke test run: | export OC_DATA_DIR="$PWD/.github-test" sbcl --non-interactive \ --eval '(load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))' \ --eval "(push (truename \"$PWD/\") asdf:*central-registry*)" \ --eval "(push (truename \"$OC_DATA_DIR/\") asdf:*central-registry*)" \ --eval "(ql:quickload '(:opencortex :croatoan))" \ --eval "(setf (uiop:getenv \"OC_DATA_DIR\") \"$OC_DATA_DIR\")" \ --eval '(opencortex:main)' \ > /tmp/oc-daemon.log 2>&1 & DAEMON_PID=$! for i in $(seq 1 20); do if ss -tln 2>/dev/null | grep -q 9105; then echo "✓ Daemon ready on port 9105" # Read the initial handshake via a short TCP connection timeout 3 bash -c 'exec 3<>/dev/tcp/localhost/9105; head -c 200 <&3' 2>/dev/null | grep -q "handshake" && \ echo "✓ Protocol handshake received" break fi sleep 1 done kill $DAEMON_PID 2>/dev/null || true wait $DAEMON_PID 2>/dev/null || true echo "✓ Daemon smoke test passed"