Initial commit: extracted from memex
This commit is contained in:
85
tests/cognitive-loop-tests.lisp
Normal file
85
tests/cognitive-loop-tests.lisp
Normal file
@@ -0,0 +1,85 @@
|
||||
(defpackage :org-agent-cognitive-tests
|
||||
(:use :cl :fiveam :org-agent))
|
||||
(in-package :org-agent-cognitive-tests)
|
||||
|
||||
(def-suite cognitive-suite
|
||||
:description "Verification of the Perceive-Think-Decide-Act loop.")
|
||||
(in-suite cognitive-suite)
|
||||
|
||||
(defun setup-mock-skills ()
|
||||
"Register mock skills for testing."
|
||||
(clrhash org-agent::*skills-registry*)
|
||||
|
||||
(org-agent::defskill :mock-refactor
|
||||
:priority 100
|
||||
:trigger (lambda (ctx) (eq (getf (getf ctx :payload) :command) :organize-subtree))
|
||||
:neuro (lambda (ctx) "Mock neuro prompt")
|
||||
:symbolic (lambda (action ctx)
|
||||
`(:type :REQUEST :id 123
|
||||
:payload (:action :refactor-subtree
|
||||
:target-id nil
|
||||
:properties (("ID" . "node-123"))))))
|
||||
|
||||
(org-agent::defskill :mock-safety
|
||||
:priority 50
|
||||
:trigger (lambda (ctx) t) ; always triggers
|
||||
:neuro (lambda (ctx) "Mock neuro")
|
||||
:symbolic (lambda (action ctx) nil))) ; rejects everything
|
||||
|
||||
(test test-perceive-ingestion
|
||||
"Perceive should update the object store and return context."
|
||||
(clrhash org-agent::*object-store*)
|
||||
(let* ((stimulus '(:type :EVENT :payload (:sensor :buffer-update :ast (:type :HEADLINE :properties (:ID "test-node" :TITLE "Test") :contents nil))))
|
||||
(context (perceive stimulus)))
|
||||
(is (equal stimulus context))
|
||||
(is (not (null (gethash "test-node" org-agent::*object-store*))))))
|
||||
|
||||
(test test-decide-safety-gate
|
||||
"Decide should block unsafe LLM proposals (System 2 bouncer)."
|
||||
(setup-mock-skills)
|
||||
(let ((context '(:type :EVENT :payload (:sensor :buffer-update)))
|
||||
(unsafe-proposal '(:type :REQUEST :payload (:action :eval :code "(shell-command \"rm -rf /\")"))))
|
||||
(let ((decision (decide unsafe-proposal context)))
|
||||
(is (eq :LOG (getf decision :type)))
|
||||
(is (search "Blocked by Global Safety Heuristic" (getf (getf decision :payload) :text))))))
|
||||
|
||||
(test test-decide-deterministic-override
|
||||
"Decide should pre-empt LLM for deterministic tasks like missing IDs."
|
||||
(setup-mock-skills)
|
||||
(let* ((ast '(:type :HEADLINE :properties (:TITLE "No ID") :contents nil))
|
||||
(context `(:type :EVENT :payload (:sensor :user-command :command :organize-subtree :ast ,ast)))
|
||||
(dummy-proposal '(:type :LOG :payload (:text "I am thinking..."))))
|
||||
(let ((decision (decide dummy-proposal context)))
|
||||
(is (eq :REQUEST (getf decision :type)))
|
||||
(is (eq :refactor-subtree (getf (getf decision :payload) :action)))
|
||||
(is (not (null (assoc "ID" (getf (getf decision :payload) :properties) :test #'string=)))))))
|
||||
|
||||
(test test-env-loading
|
||||
"Verify that environment variables are accessible (Phase 2 gating)."
|
||||
(is (not (null (uiop:getenv "LLM_ENDPOINT"))))
|
||||
(is (stringp (org-agent::get-env "MEMEX_USER"))))
|
||||
|
||||
(test test-path-resolution
|
||||
"Verify that context-resolve-path expands environment variables."
|
||||
(let ((path "$MEMEX_USER/test"))
|
||||
(is (search "Amr/test" (context-resolve-path path)))))
|
||||
|
||||
(test test-skill-dependencies
|
||||
"Verify that resolve-skill-dependencies correctly flattens the graph."
|
||||
(setup-mock-skills)
|
||||
;; Add a dependent skill
|
||||
(org-agent::defskill :mock-dependent
|
||||
:priority 10
|
||||
:dependencies '("mock-safety")
|
||||
:trigger (lambda (ctx) nil)
|
||||
:neuro nil
|
||||
:symbolic nil)
|
||||
(let ((deps (org-agent::resolve-skill-dependencies "mock-dependent")))
|
||||
(is (member "mock-safety" deps :test #'string-equal))
|
||||
(is (member "mock-dependent" deps :test #'string-equal))))
|
||||
|
||||
(test test-log-buffering
|
||||
"Verify that kernel-log correctly populates the system logs."
|
||||
(kernel-log "PSF TEST LOG")
|
||||
(let ((logs (context-get-system-logs 5)))
|
||||
(is (cl:some (lambda (line) (search "PSF TEST LOG" line)) logs))))
|
||||
36
tests/oacp-tests.lisp
Normal file
36
tests/oacp-tests.lisp
Normal file
@@ -0,0 +1,36 @@
|
||||
(defpackage :org-agent-tests
|
||||
(:use :cl :fiveam :org-agent))
|
||||
(in-package :org-agent-tests)
|
||||
|
||||
(def-suite oacp-suite
|
||||
:description "Test suite for org-agent Communication Protocol (OACP)")
|
||||
(in-suite oacp-suite)
|
||||
|
||||
(test test-framing
|
||||
"Verify that messages are correctly prefixed with a 6-character hex length."
|
||||
(let ((msg "(:type :EVENT :payload (:action :handshake))"))
|
||||
;; As the Analyst, I expect a function 'frame-message' to exist
|
||||
(is (string= "00002c(:type :EVENT :payload (:action :handshake))"
|
||||
(org-agent:frame-message msg)))))
|
||||
|
||||
(test test-parse-message
|
||||
"Verify that incoming framed strings are parsed into Lisp plists."
|
||||
(let ((framed "00002c(:type :EVENT :payload (:action :handshake))"))
|
||||
(is (equal '(:type :EVENT :payload (:action :handshake))
|
||||
(org-agent:parse-message framed)))))
|
||||
|
||||
(test test-hello-handshake
|
||||
"Verify the structure of the HELLO handshake message."
|
||||
(let ((hello (org-agent:make-hello-message "0.1.0")))
|
||||
(is (eq :EVENT (getf hello :type)))
|
||||
(is (eq :handshake (getf (getf hello :payload) :action)))
|
||||
(is (string= "0.1.0" (getf (getf hello :payload) :version)))))
|
||||
|
||||
(test test-find-missing-id
|
||||
"Verify that the daemon can find a headline missing an ID."
|
||||
(let* ((ast '(:type :org-data :contents
|
||||
((:type :HEADLINE :properties (:TITLE "No ID Here") :contents nil)
|
||||
(:type :HEADLINE :properties (:ID "exists" :TITLE "Has ID") :contents nil))))
|
||||
(found (org-agent::find-headline-missing-id ast)))
|
||||
(is (not (null found)))
|
||||
(is (string= "No ID Here" (getf (getf found :properties) :TITLE)))))
|
||||
73
tests/org-agent-test.el
Normal file
73
tests/org-agent-test.el
Normal file
@@ -0,0 +1,73 @@
|
||||
;;; org-agent-test.el --- Tests for the org-agent Emacs stub
|
||||
|
||||
(require 'ert)
|
||||
(require 'cl-lib)
|
||||
(require 'org-agent "/home/amr/.openclaw/workspace/memex/5_projects/org-agent/src/org-agent.el")
|
||||
|
||||
(ert-deftest test-org-agent-framing ()
|
||||
"Verify that org-agent-send correctly frames a plist."
|
||||
(let ((captured-framed nil))
|
||||
(cl-letf (((symbol-function 'process-send-string)
|
||||
(lambda (proc string) (setq captured-framed string)))
|
||||
((symbol-function 'process-live-p) (lambda (proc) t))
|
||||
(org-agent--process t))
|
||||
(org-agent-send '(:type :EVENT :id 1))
|
||||
(should (string= "000014(:type :EVENT :id 1)" captured-framed)))))
|
||||
|
||||
(ert-deftest test-org-agent-parsing ()
|
||||
"Verify that the filter correctly parses OACP framed messages."
|
||||
(let ((mock-buffer (generate-new-buffer " *org-agent-test*"))
|
||||
(received-plist nil))
|
||||
(cl-letf (((symbol-function 'org-agent--handle-message)
|
||||
(lambda (proc plist) (setq received-plist plist))))
|
||||
(with-current-buffer mock-buffer
|
||||
(insert "000014(:type :EVENT :id 1)")
|
||||
(org-agent--process-buffer mock-buffer)
|
||||
(should (equal '(:type :EVENT :id 1) received-plist))
|
||||
(should (= (buffer-size) 0))))))
|
||||
|
||||
(ert-deftest test-org-agent-actuator-message ()
|
||||
"Verify that the :message actuator works."
|
||||
(let ((org-agent--process nil)
|
||||
(captured-response nil))
|
||||
(cl-letf (((symbol-function 'org-agent-send)
|
||||
(lambda (plist) (setq captured-response plist))))
|
||||
(org-agent--execute-request nil 101 '(:action :message :text "Hello from Daemon"))
|
||||
;; Check that we sent a success response back
|
||||
(should (eq :RESPONSE (plist-get captured-response :type)))
|
||||
(should (eq :success (plist-get (plist-get captured-response :payload) :status))))))
|
||||
|
||||
(ert-deftest test-org-agent-run-command ()
|
||||
"Verify that org-agent-run-command sends the correct event."
|
||||
(let ((captured-framed nil))
|
||||
(cl-letf (((symbol-function 'process-send-string)
|
||||
(lambda (proc string) (setq captured-framed string)))
|
||||
((symbol-function 'process-live-p) (lambda (proc) t))
|
||||
(org-agent--process t))
|
||||
(org-agent-run-command :test-cmd)
|
||||
(should (string-match-p ":sensor :user-command" captured-framed))
|
||||
(should (string-match-p ":command :test-cmd" captured-framed)))))
|
||||
|
||||
(ert-deftest test-org-agent-ast-cleaning ()
|
||||
"Verify that org-agent--clean-element produces a pure plist."
|
||||
(let* ((org-text "* Hello\nWorld")
|
||||
(ast (with-temp-buffer
|
||||
(org-mode)
|
||||
(insert org-text)
|
||||
(org-element-parse-buffer)))
|
||||
(cleaned (org-agent--clean-element ast)))
|
||||
(should (plist-get cleaned :type))
|
||||
(should (eq 'org-data (plist-get cleaned :type)))
|
||||
;; Check that children exist
|
||||
(should (plist-get (car (plist-get cleaned :contents)) :type))
|
||||
;; Check that we didn't leak buffer objects
|
||||
(should-not (plist-get (plist-get cleaned :properties) :buffer))))
|
||||
|
||||
(ert-deftest test-org-agent-actuator-eval ()
|
||||
"Verify that the :eval actuator can execute elisp."
|
||||
(let ((org-agent--process nil)
|
||||
(captured-response nil))
|
||||
(cl-letf (((symbol-function 'org-agent-send)
|
||||
(lambda (plist) (setq captured-response plist))))
|
||||
(org-agent--execute-request nil 102 '(:action :eval :code "(+ 1 2)"))
|
||||
(should (equal "3" (plist-get (plist-get captured-response :payload) :result))))))
|
||||
Reference in New Issue
Block a user