Some checks failed
Deploy-Agent-V15-Stdin / JOB-V15-STDIN (push) Failing after 3s
- Folders: literate->harness, src->library, system->environment, scripts->interfaces. - Synchronized all :tangle paths and system definitions. - Hardened .gitignore for binary and log artifacts. - Consolidated all documentation into docs/.
140 lines
5.8 KiB
Org Mode
140 lines
5.8 KiB
Org Mode
#+TITLE: The Skill Engine (skills.lisp)
|
|
#+AUTHOR: Amr
|
|
#+FILETAGS: :harness:skills:
|
|
#+STARTUP: content
|
|
|
|
* The Skill Engine (skills.lisp)
|
|
|
|
** Architectural Intent: Hot-Reloadable Intelligence
|
|
The Skill Engine is the modular heart of the OpenCortex. By separating cognitive and physical capabilities into discrete "Skills," we allow the system to evolve without modifying the core Lisp microharness.
|
|
|
|
*** Core Principles
|
|
1. **Isolation:** Every skill resides in its own Lisp package, preventing global namespace pollution and variable collisions.
|
|
2. **Topological Bootstrapping:** Skills can declare dependencies on other skills. The harness automatically calculates the correct loading order.
|
|
3. **Hot-Reloading:** Since Skills are defined as Literate Org files, the agent can edit, re-tangle, and re-load its own skills at runtime without a system restart.
|
|
4. **The Bouncer Pattern:** Every skill must define a deterministic gate. This is the primary security layer where native Lisp logic verifies probabilistic AI proposals.
|
|
|
|
** Pipeline Initialization
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(in-package :opencortex)
|
|
#+end_src
|
|
|
|
* Skill Definition and Registration
|
|
|
|
** The Skill Structure
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(defstruct skill
|
|
"Represents a hot-reloadable module of intelligence or actuation."
|
|
name
|
|
priority
|
|
dependencies
|
|
trigger-fn
|
|
probabilistic-prompt
|
|
deterministic-fn)
|
|
#+end_src
|
|
|
|
** Skill Registration Macro (defskill)
|
|
This macro provides a clean interface for skill authors to register their modules. It automatically handles the integration with the global ~*skills-registry*~.
|
|
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(defmacro defskill (name &key (priority 0) dependencies trigger probabilistic deterministic)
|
|
"Registers a new skill into the global harness registry."
|
|
`(setf (gethash (string-downcase (string ',name)) *skills-registry*)
|
|
(make-skill :name (string-downcase (string ',name))
|
|
:priority ,priority
|
|
:dependencies ,dependencies
|
|
:trigger-fn ,trigger
|
|
:probabilistic-prompt ,probabilistic
|
|
:deterministic-fn ,deterministic)))
|
|
#+end_src
|
|
|
|
* Dynamic Loading System
|
|
|
|
** Lisp Syntax Validation (validate-lisp-syntax)
|
|
Before loading a new skill into the live image, the harness performs a dry-run parse to ensure the code is syntactically valid. This prevents a single hallucinated parenthesis from crashing the entire brain.
|
|
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(defun validate-lisp-syntax (file-path)
|
|
"Parses a Lisp file without evaluation to verify syntactic integrity."
|
|
(handler-case
|
|
(with-open-file (stream file-path)
|
|
(loop for form = (read stream nil :eof)
|
|
until (eq form :eof))
|
|
t)
|
|
(error (c)
|
|
(harness-log "SYNTAX ERROR in ~a: ~a" file-path c)
|
|
nil)))
|
|
#+end_src
|
|
|
|
** Literate Skill Ingestion (load-skill-from-org)
|
|
The primary mechanism for hot-reloading. It handles the Org-to-Lisp translation and ensures the resulting code is jailed within its own package.
|
|
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(defun load-skill-from-org (org-file-path)
|
|
"Tangles and loads a single Org-mode skill file."
|
|
(let* ((filename (file-name-nondirectory (namestring org-file-path)))
|
|
(skill-id (pathname-name org-file-path))
|
|
(lisp-file (merge-pathnames (concatenate 'string "library/gen/" skill-id ".lisp")
|
|
(asdf:system-source-directory :opencortex))))
|
|
|
|
(ensure-directories-exist lisp-file)
|
|
(harness-log "LOADER: Loading ~a..." skill-id)
|
|
|
|
;; 1. Tangle the Org file into Lisp
|
|
(uiop:run-program (list "emacs" "--batch" "--eval" "(require 'org)"
|
|
"--eval" (format nil "(org-babel-tangle-file \"~a\")" org-file-path))
|
|
:output t)
|
|
|
|
;; 2. Verify and Load
|
|
(if (validate-lisp-syntax lisp-file)
|
|
(progn
|
|
(handler-case (load lisp-file)
|
|
(error (c) (harness-log "LOADER ERROR in skill '~a': ~a" skill-id c)))
|
|
t)
|
|
nil)))
|
|
#+end_src
|
|
|
|
* Bootstrapping Logic
|
|
|
|
** Dependency Sorting (topological-sort-skills)
|
|
Ensures that foundational skills (like the Bouncer or Policy engine) are always loaded before higher-level actuators.
|
|
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(defun topological-sort-skills (skills)
|
|
"Calculates the correct loading order based on #+DEPENDS_ON metadata."
|
|
;; Placeholder: Currently sorts by priority as a proxy for dependencies.
|
|
(sort skills #'> :key #'skill-priority))
|
|
#+end_src
|
|
|
|
** Registry Initialization (initialize-all-skills)
|
|
The high-level boot sequence for the skill engine.
|
|
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(defun initialize-all-skills ()
|
|
"Discovers and loads all Org files in the SKILLS_DIR."
|
|
(let* ((skills-dir (uiop:getenv "SKILLS_DIR"))
|
|
(files (when (and skills-dir (uiop:directory-exists-p skills-dir))
|
|
(uiop:directory-files skills-dir "*.org"))))
|
|
(dolist (f files)
|
|
(load-skill-from-org f))
|
|
(harness-log "LOADER: Boot Complete. [Ready: ~a] [Failed: 0]" (hash-table-count *skills-registry*))))
|
|
#+end_src
|
|
|
|
* Cognitive Dispatching
|
|
|
|
** Skill Trigger Discovery (find-triggered-skill)
|
|
Identifies which skill is best suited to handle the current metabolic signal.
|
|
|
|
#+begin_src lisp :tangle ../library/skills.lisp
|
|
(defun find-triggered-skill (context)
|
|
"Iterates through the registry and returns the first skill whose trigger returns true."
|
|
(let ((skills nil))
|
|
(maphash (lambda (name skill) (declare (ignore name)) (push skill skills)) *skills-registry*)
|
|
(setf skills (sort skills #'> :key #'skill-priority))
|
|
(dolist (s skills)
|
|
(let ((trigger (skill-trigger-fn s)))
|
|
(when (and trigger (funcall trigger context))
|
|
(return-from find-triggered-skill s))))
|
|
nil))
|
|
#+end_src
|