(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))))