diff --git a/skills/org-skill-config-manager.org b/skills/org-skill-config-manager.org index 056498c..12dac30 100644 --- a/skills/org-skill-config-manager.org +++ b/skills/org-skill-config-manager.org @@ -41,6 +41,55 @@ Secrets are appended to `~/.config/opencortex/.env`, while structural metadata i (let ((opencortex::*providers* nil)) (opencortex:register-provider :ollama '(:url "http://localhost:11434")) (is (equal "http://localhost:11434" (getf (getf opencortex::*providers* :ollama) :url))))) + +(test test-get-oc-config-dir-default + "Verify get-oc-config-dir returns XDG-compliant path when env not set." + (let ((orig-env (uiop:getenv "OC_CONFIG_DIR"))) + (unwind-protect + (progn + (setf (uiop:getenv "OC_CONFIG_DIR") nil) + (let ((dir (opencortex:get-oc-config-dir))) + (is (search ".config/opencortex" (namestring dir))))) + (if orig-env + (setf (uiop:getenv "OC_CONFIG_DIR") orig-env) + (unsetenv "OC_CONFIG_DIR"))))) + +(test test-get-oc-config-dir-env-override + "Verify get-oc-config-dir uses OC_CONFIG_DIR when set." + (let ((orig-env (uiop:getenv "OC_CONFIG_DIR"))) + (unwind-protect + (progn + (setf (uiop:getenv "OC_CONFIG_DIR") "/tmp/test-opencortex-config") + (let ((dir (opencortex:get-oc-config-dir))) + (is (string= "/tmp/test-opencortex-config/" (namestring dir))))) + (if orig-env + (setf (uiop:getenv "OC_CONFIG_DIR") orig-env) + (unsetenv "OC_CONFIG_DIR"))))) + +(test test-save-providers-roundtrip + "Verify save-providers writes and providers can be reloaded." + (let ((opencortex::*providers* nil) + (test-dir "/tmp/test-opencortex-config/") + (orig-env (uiop:getenv "OC_CONFIG_DIR"))) + (unwind-protect + (progn + (setf (uiop:getenv "OC_CONFIG_DIR") test-dir) + (opencortex:register-provider :openai '(:key "test-key-123" :model "gpt-4")) + (opencortex:save-providers) + (let ((loaded-provs (uiop:read-file-string (merge-pathnames "providers.lisp" (uiop:ensure-directory-pathname test-dir))))) + (is (search "openai" loaded-provs)) + (is (search "test-key-123" loaded-provs)))) + (uiop:delete-directory-tree (uiop:ensure-directory-pathname test-dir) :validate t) + (if orig-env + (setf (uiop:getenv "OC_CONFIG_DIR") orig-env) + (unsetenv "OC_CONFIG_DIR"))))) + +(test test-configure-provider-validation + "Verify configure-provider validates required fields." + (let ((opencortex::*providers* nil)) + (opencortex:register-provider :ollama '(:url "http://localhost:11434")) + (let ((cfg (getf opencortex::*providers* :ollama))) + (is (equal "http://localhost:11434" (getf cfg :url)))))) #+end_src * Phase C: Implementation (Build) diff --git a/skills/org-skill-gateway-manager.org b/skills/org-skill-gateway-manager.org index 9cb844a..b48ab3b 100644 --- a/skills/org-skill-gateway-manager.org +++ b/skills/org-skill-gateway-manager.org @@ -38,6 +38,32 @@ In a traditional AI wrapper, the user manually edits a config file to add a bot (let ((opencortex::*gateways* nil)) (opencortex:skill-gateway-register :telegram '(:status :unverified)) (is (getf (getf opencortex::*gateways* :telegram) :status)))) + +(test test-gateway-multiple-platforms + "Verify that multiple gateways can be registered simultaneously." + (let ((opencortex::*gateways* nil)) + (opencortex:skill-gateway-register :telegram '(:status :verified :token "abc123")) + (opencortex:skill-gateway-register :signal '(:status :unverified)) + (is (eq (getf (getf opencortex::*gateways* :telegram) :status) :verified)) + (is (eq (getf (getf opencortex::*gateways* :signal) :status) :unverified)))) + +(test test-save-gateways-roundtrip + "Verify save-gateways persists and gateways can be verified." + (let ((opencortex::*gateways* nil) + (test-dir "/tmp/test-opencortex-gw/") + (orig-env (uiop:getenv "OC_CONFIG_DIR"))) + (unwind-protect + (progn + (setf (uiop:getenv "OC_CONFIG_DIR") test-dir) + (opencortex:skill-gateway-register :telegram '(:status :verified :chat-id 12345)) + (opencortex:save-gateways) + (let ((loaded-gw (uiop:read-file-string (merge-pathnames "gateways.lisp" (uiop:ensure-directory-pathname test-dir))))) + (is (search "telegram" loaded-gw)) + (is (search "12345" loaded-gw)))) + (uiop:delete-directory-tree (uiop:ensure-directory-pathname test-dir) :validate t) + (if orig-env + (setf (uiop:getenv "OC_CONFIG_DIR") orig-env) + (unsetenv "OC_CONFIG_DIR"))))) #+end_src * Phase C: Implementation (Build) diff --git a/skills/org-skill-self-edit.org b/skills/org-skill-self-edit.org index f8cafec..b99af70 100644 --- a/skills/org-skill-self-edit.org +++ b/skills/org-skill-self-edit.org @@ -274,6 +274,52 @@ Swap compiled skill files without breaking active sockets. (test balance-parens-empty (let ((result (opencortex::self-edit-balance-parens ""))) (is (string= result "")))) + +(test test-self-edit-apply-success + "Verify self-edit-apply performs surgical replacement correctly." + (let ((test-file "/tmp/self-edit-test.lisp")) + (unwind-protect + (progn + (with-open-file (out test-file :direction :output :if-exists :supersede) + (write-string "(defun hello () (format t \"world~%\"))" out)) + (let ((result (opencortex::self-edit-apply test-file "world" "universe"))) + (is (eq (getf result :status) :success)) + (let ((content (uiop:read-file-string test-file))) + (is (search "universe" content)) + (is (not (search "world" content)))))) + (uiop:delete-file-if-exists test-file)))) + +(test test-self-edit-apply-not-found + "Verify self-edit-apply returns error when pattern not found." + (let ((test-file "/tmp/self-edit-test2.lisp")) + (unwind-protect + (progn + (with-open-file (out test-file :direction :output :if-exists :supersede) + (write-string "(defun hello () t)" out)) + (let ((result (opencortex::self-edit-apply test-file "nonexistent-pattern" "new"))) + (is (eq (getf result :status) :error)) + (is (search "not found" (getf result :message))))) + (uiop:delete-file-if-exists test-file)))) + +(test test-self-edit-apply-file-not-found + "Verify self-edit-apply returns error when file does not exist." + (let ((result (opencortex::self-edit-apply "/nonexistent/path/file.lisp" "old" "new"))) + (is (eq (getf result :status) :error)) + (is (search "not found" (getf result :message))))) + +(test test-self-edit-parse-location-from-payload + "Verify self-edit-parse-location extracts file/line from payload." + (let ((context '(:payload (:file "/tmp/test.lisp" :line 42 :message "error")))) + (let ((result (opencortex::self-edit-parse-location context))) + (is (equal "/tmp/test.lisp" (getf result :file))) + (is (eq 42 (getf result :line)))))) + +(test test-self-edit-parse-location-from-message + "Verify self-edit-parse-location extracts file/line from error message." + (let ((context '(:payload (:message "Error in /home/user/project/foo.lisp at line 99")))) + (let ((result (opencortex::self-edit-parse-location context))) + (is (search "foo.lisp" (getf result :file))) + (is (eq 99 (getf result :line)))))) #+end_src * See Also