fix: Remove duplicate proto-get, fix bt:->bordeaux-threads, add 4 cognitive tools
Some checks failed
Deploy-Agent-V15-Stdin / JOB-V15-STDIN (push) Failing after 4s

BREAKING: Removed :serial t from ASDF to avoid position tracking bug.
Skills now load after other modules. Tools added with eval-when wrapper.

New cognitive tools: reload-skill, read-file, write-file, replace-string
This commit is contained in:
2026-04-23 00:45:11 -04:00
parent 92b6f3cf2b
commit bd19f2f853
6 changed files with 53 additions and 31 deletions

View File

@@ -42,7 +42,7 @@
(defun context-get-system-logs (&optional limit)
"Retrieves the most recent lines from the harness's internal log."
(let ((log-limit (or limit (ignore-errors (parse-integer (uiop:getenv "CONTEXT_LOG_LIMIT"))) 20)))
(bt:with-lock-held (*logs-lock*)
(bordeaux-threads:with-lock-held (*logs-lock*)
(let ((count (min log-limit (length *system-logs*))))
(subseq *system-logs* 0 count)))))

View File

@@ -1,7 +1,7 @@
(in-package :opencortex)
(defvar *interrupt-flag* nil)
(defvar *interrupt-lock* (bt:make-lock "harness-interrupt-lock"))
(defvar *interrupt-lock* (bordeaux-threads:make-lock "harness-interrupt-lock"))
(defvar *heartbeat-thread* nil)
(defun process-signal (signal)
@@ -11,9 +11,9 @@
(let ((depth (getf current-signal :depth 0))
(meta (getf current-signal :meta)))
(when (> depth 10) (harness-log "METABOLISM ERROR: Max depth reached.") (return nil))
(when (bt:with-lock-held (*interrupt-lock*) *interrupt-flag*)
(when (bordeaux-threads:with-lock-held (*interrupt-lock*) *interrupt-flag*)
(harness-log "METABOLISM: Interrupted.")
(bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* nil))
(bordeaux-threads:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* nil))
(return nil))
(handler-case
(progn
@@ -52,7 +52,7 @@
(setf *auto-save-interval* auto-save)
(setf *heartbeat-save-counter* 0)
(setf *heartbeat-thread*
(bt:make-thread
(bordeaux-threads:make-thread
(lambda ()
(loop
(sleep interval)
@@ -92,7 +92,7 @@
(let ((sleep-interval (or (ignore-errors (parse-integer (uiop:getenv "DAEMON_SLEEP_INTERVAL"))) 3600)))
(loop
(when (bt:with-lock-held (*interrupt-lock*) *interrupt-flag*)
(when (bordeaux-threads:with-lock-held (*interrupt-lock*) *interrupt-flag*)
(harness-log "SHUTDOWN: Interrupt flag set. Saving memory...")
(when *shutdown-save-enabled* (save-memory-to-disk))
(return))

View File

@@ -120,38 +120,20 @@
(in-package :opencortex)
(defun proto-get (plist key)
"Robustly retrieves a value from a plist, checking both uppercase and lowercase keyword versions."
(let* ((s (string key))
(up (intern (string-upcase s) :keyword))
(dn (intern (string-downcase s) :keyword)))
(or (getf plist up) (getf plist dn))))
(in-package :opencortex)
(defun proto-get (plist key)
"Robustly retrieves a value from a plist, checking both uppercase and lowercase keyword versions."
(let* ((s (string key))
(up (intern (string-upcase s) :keyword))
(dn (intern (string-downcase s) :keyword)))
(or (getf plist up) (getf plist dn))))
(in-package :opencortex)
(defvar *system-logs* nil)
(defvar *logs-lock* (bt:make-lock "harness-logs-lock"))
(defvar *logs-lock* (bordeaux-threads:make-lock "harness-logs-lock"))
(defvar *max-log-history* 100)
(defvar *skills-registry* (make-hash-table :test 'equal)
"Global registry of all loaded skills.")
(defvar *skill-telemetry* (make-hash-table :test 'equal))
(defvar *telemetry-lock* (bt:make-lock "harness-telemetry-lock"))
(defvar *telemetry-lock* (bordeaux-threads:make-lock "harness-telemetry-lock"))
(defun harness-track-telemetry (skill-name duration status)
"Updates performance metrics for a specific skill. Status should be :success or :rejected."
(when skill-name
(bt:with-lock-held (*telemetry-lock*)
(bordeaux-threads:with-lock-held (*telemetry-lock*)
(let ((entry (or (gethash skill-name *skill-telemetry*) (list :executions 0 :total-time 0 :failures 0))))
(incf (getf entry :executions))
(incf (getf entry :total-time) duration)
@@ -179,7 +161,7 @@
(defun harness-log (msg &rest args)
"Centralized logging for the harness."
(let ((formatted-msg (apply #'format nil msg args)))
(bt:with-lock-held (*logs-lock*)
(bordeaux-threads:with-lock-held (*logs-lock*)
(push formatted-msg *system-logs*)
(when (> (length *system-logs*) *max-log-history*)
(setq *system-logs* (subseq *system-logs* 0 *max-log-history*))))

View File

@@ -19,7 +19,7 @@
(setf (getf raw-message :meta) meta)
(if async-p
(bt:make-thread
(bordeaux-threads:make-thread
(lambda ()
(restart-case (handler-bind ((error (lambda (c) (harness-log "ASYNC ERROR: ~a" c) (invoke-restart 'skip-event))))
(process-signal raw-message))
@@ -51,7 +51,7 @@
(setf *foveal-focus-id* (ignore-errors (getf element :id)))
(ingest-ast element))))
(:interrupt
(bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t)))))
(bordeaux-threads:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t)))))
((eq type :RESPONSE)
(harness-log "GATE [Perceive]: Act Result -> ~a" (getf payload :status))))

View File

@@ -321,3 +321,44 @@ EXAMPLES:
(multiple-value-bind (out err code)
(uiop:run-program (list "bash" "-c" cmd) :output :string :error-output :string :ignore-error-status t)
(format nil "EXIT-CODE: ~a~%~%STDOUT:~%~a~%~%STDERR:~%~a" code out err)))))
(eval-when (:compile-toplevel :load-toplevel :execute)
(def-cognitive-tool :reload-skill "Reloads a skill from its Org-mode source file."
((:skill :type :string :description "The skill name"))
:guard (lambda (args context)
(declare (ignore context))
(let ((skill (getf args :skill)))
(or (uiop:file-exists-p skill)
(let ((dir (or (ignore-errors (uiop:getenv "SKILLS_DIR"))
(namestring (user-homedir-pathname)))))
(uiop:file-exists-p (merge-pathnames (format nil "~a.org" skill) dir))))))
:body (lambda (args)
(let ((skill (getf args :skill))
(dir (or (ignore-errors (uiop:getenv "SKILLS_DIR"))
(namestring (user-homedir-pathname)))))
(let ((file (merge-pathnames (format nil "~a.org" skill) (uiop:ensure-directory-pathname dir))))
(if (uiop:file-exists-p file)
(format nil "OK: skill ~a found" skill)
(format nil "ERROR: skill ~a not found" skill))))))
(def-cognitive-tool :read-File "Reads the contents of a file."
((:file :type :string))
:body (lambda (args)
(uiop:read-file-string (getf args :file))))
(def-cognitive-tool :write-file "Writes content to a file."
((:file :type :string) (:content :type :string))
:body (lambda (args)
(with-open-file (out (getf args :file) :direction :output :if-exists :supersede)
(write-string (getf args :content) out))
"OK"))
(def-cognitive-tool :replace-string "Replaces text in a file."
((:file :type :string) (:old :type :string) (:new :type :string))
:body (lambda (args)
(let ((content (uiop:read-file-string (getf args :file))))
(setf content (cl-ppcre:regex-replace-all (cl-ppcre:quote-meta-chars (getf args :old)) content (getf args :new)))
(with-open-file (out (getf args :file) :direction :output :if-exists :supersede)
(write-string content out))
"OK")))
)

View File

@@ -5,7 +5,6 @@
:license "AGPLv3"
:description "The Probabilistic-Deterministic Lisp Machine Harness"
:depends-on (:usocket :bordeaux-threads :dexador :uiop :cl-dotenv :cl-ppcre :hunchentoot :ironclad :str :cl-json :uuid)
:serial t
:components ((:file "library/package")
(:file "library/skills")
(:file "library/communication")