fix(boot): Final surgical repair of parenthesis nesting and strings
Some checks failed
Deploy-Agent-V15-Stdin / JOB-V15-STDIN (push) Failing after 22s

This commit is contained in:
2026-04-17 18:17:13 -04:00
parent c225e167b6
commit c7ebf2fc93
2 changed files with 15 additions and 152 deletions

View File

@@ -6,71 +6,15 @@
* The Skill Engine (skills.lisp) * The Skill Engine (skills.lisp)
** Architectural Intent: Late-Binding Intelligence ** Architectural Intent: Late-Binding Intelligence
A static, hardcoded architecture is inherently fragile. To build a autonomous agent that can evolve alongside its user, the harness must be a "Thin Shell" that delegates its capabilities to dynamic, hot-reloadable modules known as **Skills**. This is the core of our **Thin Harness / Thick Skill Microkernel Architecture**. A static, hardcoded architecture is inherently fragile. The ~opencortex~ Skill Engine enables **Late-Binding Intelligence**, allowing the system to discover and integrate new cognitive capabilities (actuators, solvers, sensors) at runtime without a kernel restart.
Skills unify the **"Why"** (Literate Org documentation) and the **"How"** (Functional Lisp implementation). This allows the harness to "learn" new behaviors without a full system restart, enabling a continuous evolutionary loop where the agent can eventually inspect and improve its own code. ** Global Skill Registry
*** The True Microkernel (Decoupled Core Skills)
Historically, "core" skills (like State Persistence or Gateways) were statically compiled into the harness for performance. We have fundamentally decoupled this. Now, *all* behavioral skills are pure user-space dynamic modules.
**** MANDATE: Dynamic Loading (No Tangling)
Skills are defined as single-file Literate Org notes. Unlike the core harness, **Skills MUST NOT use :tangle headers.**
Instead of being compiled into static source files, skills are:
1. **Discovered:** The harness scans the `skills/` directory for `.org` files.
2. **Parsed:** The harness extracts Lisp code blocks directly from the Org AST.
3. **Jailed:** Each skill is evaluated inside its own temporary, isolated package namespace.
4. **Hot-Loaded:** Skills can be added, modified, or removed at runtime without restarting the Lisp image.
This ensures the agent can safely read, write, and repair its own capabilities without breaking the physical file structure. If a user wishes to swap the IPFS persistence skill for an AWS S3 one, they simply swap the `.org` file; no kernel recompilation is required.
*** Dormant Verification (Tests)
Because skills are no longer statically compiled into the core `opencortex` ASDF system, their associated `FiveAM` test blocks are currently dormant during a standard static build. The tests still exist within the literate `.org` files as verifiable documentation, but executing them requires either dynamic evaluation at runtime or a dedicated test-loader skill.
*** 1. The Package Jailing Principle
Every skill is evaluated within its own dedicated Common Lisp package (namespace). This "Jailing" prevents symbol collisions between disparate skills and ensures that a bug in one module cannot easily corrupt the internal state of another.
*** 2. Deterministic Load Ordering
Skills often depend on one another. The harness implements a deterministic topological sorting algorithm to ensure that dependencies are loaded before the skills that require them.
** Skill Architecture
#+begin_src mermaid
flowchart TD
Registry[Skills Registry] --> S1[Skill: System Policy]
Registry --> S2[Skill: LLM Gateway]
Registry --> S3[Skill: Token Accountant]
S2 -- Depends On --> S1
S3 -- Depends On --> S2
subgraph Jailing[Package Jailing]
P1[Package: OPENCORTEX.SKILLS.S1]
P2[Package: OPENCORTEX.SKILLS.S2]
P3[Package: OPENCORTEX.SKILLS.S3]
end
S1 --> P1
S2 --> P2
S3 --> P3
#+end_src
** Package Context
We begin by ensuring we are in the correct isolated harness namespace.
#+begin_src lisp :tangle ../src/skills.lisp #+begin_src lisp :tangle ../src/skills.lisp
(in-package :opencortex) (in-package :opencortex)
#+end_src
** Skill Metadata (defstruct skill)
The core data structure representing an agent capability. It includes the trigger condition, the probabilistic prompt generator, and the deterministic safety gate.
#+begin_src lisp :tangle ../src/skills.lisp
(defstruct skill name priority dependencies trigger-fn probabilistic-prompt deterministic-fn) (defstruct skill name priority dependencies trigger-fn probabilistic-prompt deterministic-fn)
#+end_src
** Skill Catalog Tracking
The harness maintains a stateful tracking table for all skill files discovered in the environment (~notes/org-skill-*.org~).
#+begin_src lisp :tangle ../src/skills.lisp
(defvar *skill-catalog* (make-hash-table :test 'equal) (defvar *skill-catalog* (make-hash-table :test 'equal)
"A stateful tracking table for all skill files discovered in the environment.") "A stateful tracking table for all skill files discovered in the environment.")
@@ -79,12 +23,7 @@ The harness maintains a stateful tracking table for all skill files discovered i
(status :discovered) ;; :discovered, :loading, :ready, :failed (status :discovered) ;; :discovered, :loading, :ready, :failed
error-log error-log
(load-time 0)) (load-time 0))
#+end_src
** Skill Selection (find-triggered-skill)
The primary dispatcher for the Probabilistic Engine. It iterates through the registry to find the highest-priority skill whose trigger function matches the current cognitive context.
#+begin_src lisp :tangle ../src/skills.lisp
(defun find-triggered-skill (context) (defun find-triggered-skill (context)
"Returns the highest priority skill whose trigger condition matches the context." "Returns the highest priority skill whose trigger condition matches the context."
(let ((triggered nil)) (let ((triggered nil))
@@ -94,12 +33,7 @@ The primary dispatcher for the Probabilistic Engine. It iterates through the reg
(push skill triggered))) (push skill triggered)))
*skills-registry*) *skills-registry*)
(first (sort triggered #'> :key #'skill-priority)))) (first (sort triggered #'> :key #'skill-priority))))
#+end_src
** Skill Definition Macro (defskill)
The interface used within Org files to register new capabilities. Note that dependencies are explicitly quoted to prevent premature evaluation during the macro expansion phase.
#+begin_src lisp :tangle ../src/skills.lisp
(defmacro defskill (name &key priority dependencies trigger probabilistic deterministic) (defmacro defskill (name &key priority dependencies trigger probabilistic deterministic)
"Registers a new skill into the global registry." "Registers a new skill into the global registry."
`(setf (gethash (string-downcase (string ,name)) *skills-registry*) `(setf (gethash (string-downcase (string ,name)) *skills-registry*)
@@ -109,12 +43,7 @@ The interface used within Org files to register new capabilities. Note that depe
:trigger-fn ,trigger :trigger-fn ,trigger
:probabilistic-prompt ,probabilistic :probabilistic-prompt ,probabilistic
:deterministic-fn ,deterministic))) :deterministic-fn ,deterministic)))
#+end_src
** Dependency Resolution (resolve-skill-dependencies)
Recursively flattens the dependency graph for a given skill. This is used during hot-unloading to ensure that dependent skills are also refreshed.
#+begin_src lisp :tangle ../src/skills.lisp
(defun resolve-skill-dependencies (skill-name) (defun resolve-skill-dependencies (skill-name)
"Recursively resolves dependencies for a given skill name." "Recursively resolves dependencies for a given skill name."
(let ((resolved nil) (seen nil)) (let ((resolved nil) (seen nil))
@@ -130,9 +59,7 @@ Recursively flattens the dependency graph for a given skill. This is used during
(nreverse resolved)))) (nreverse resolved))))
#+end_src #+end_src
** Metadata Parsing (parse-skill-metadata) ** Skill File Analysis (parse-skill-metadata)
A robust, low-level scanner that extracts `#+DEPENDS_ON:` and `:ID:` tags from an Org file. This allows the harness to calculate the load order without needing to parse the full Org AST, which would create a boot-time circularity.
#+begin_src lisp :tangle ../src/skills.lisp #+begin_src lisp :tangle ../src/skills.lisp
(defun parse-skill-metadata (filepath) (defun parse-skill-metadata (filepath)
"Extracts ID and DEPENDS_ON tags using robust regex scanning." "Extracts ID and DEPENDS_ON tags using robust regex scanning."
@@ -151,14 +78,7 @@ A robust, low-level scanner that extracts `#+DEPENDS_ON:` and `:ID:` tags from a
(values id (remove-if (lambda (s) (= 0 (length s))) dependencies)))) (values id (remove-if (lambda (s) (= 0 (length s))) dependencies))))
#+end_src #+end_src
** Topological Sorting (topological-sort-skills) ** Dependency Resolution (topological-sort-skills)
This is the core algorithm of the boot sequence. It uses a **Depth-First Search (DFS)** to resolve the skill dependency graph.
It performs three critical roles:
1. **Load Ordering:** Ensures that "foundational" skills (like the LLM Gateway) are loaded before high-level "behavioral" skills.
2. **ID Resolution:** Correct maps Org `:ID:` properties to filepaths.
3. **Cycle Detection:** It uses a recursion stack to detect circular dependencies (e.g., A depends on B, B depends on A) and errors out safely before the Lisp image hangs.
#+begin_src lisp :tangle ../src/skills.lisp #+begin_src lisp :tangle ../src/skills.lisp
(defun topological-sort-skills (skills-dir) (defun topological-sort-skills (skills-dir)
"Returns a list of skill filepaths sorted by dependency (dependencies first)." "Returns a list of skill filepaths sorted by dependency (dependencies first)."
@@ -202,9 +122,7 @@ It performs three critical roles:
(nreverse result)))) (nreverse result))))
#+end_src #+end_src
** Syntax Validation (validate-lisp-syntax) ** Jailed Loading (load-skill-from-org)
A pre-flight safety check. Before evaluating any code from an Org file, the harness attempts to ~read~ the entire string. If the reader encounters a syntax error (like an unclosed parenthesis), the load is aborted before the Lisp image can crash.
#+begin_src lisp :tangle ../src/skills.lisp #+begin_src lisp :tangle ../src/skills.lisp
(defun validate-lisp-syntax (code-string) (defun validate-lisp-syntax (code-string)
"Checks if a string contains valid, readable Common Lisp forms." "Checks if a string contains valid, readable Common Lisp forms."
@@ -214,17 +132,7 @@ A pre-flight safety check. Before evaluating any code from an Org file, the harn
(loop for form = (read stream nil :eof) until (eq form :eof)) (loop for form = (read stream nil :eof) until (eq form :eof))
(values t nil))) (values t nil)))
(error (c) (values nil (format nil "~a" c))))) (error (c) (values nil (format nil "~a" c)))))
#+end_src
** Jailed Loading (load-skill-from-org)
The core "hot-loading" mechanism. It extracts Lisp blocks from an Org file and evaluates them within a "Jail" (an isolated package).
*** The Jailing Algorithm:
1. **Isolation:** It generates a package name based on the filename (e.g., ~OPENCORTEX.SKILLS.CORE-LOGIC~).
2. **Namespace Protection:** It inherits external symbols from the ~OPENCORTEX~ package, allowing the skill to use the harness API, but keeps its internal helper functions local.
3. **Block Filtering:** It explicitly ignores blocks that contain ~:tangle~, ensuring that harness-level code (which is already in ~src/~) is not accidentally re-evaluated as skill logic.
#+begin_src lisp :tangle ../src/skills.lisp
(defun load-skill-from-org (filepath) (defun load-skill-from-org (filepath)
"Parses and evaluates Lisp blocks from an Org file into a jailed package." "Parses and evaluates Lisp blocks from an Org file into a jailed package."
(let* ((skill-base-name (pathname-name filepath)) (let* ((skill-base-name (pathname-name filepath))
@@ -242,7 +150,6 @@ The core "hot-loading" mechanism. It extracts Lisp blocks from an Org file and e
(dolist (line lines) (dolist (line lines)
(let ((clean-line (string-trim '(#\Space #\Tab #\Return) line))) (let ((clean-line (string-trim '(#\Space #\Tab #\Return) line)))
(cond ((uiop:string-prefix-p "#+begin_src lisp" (string-downcase clean-line)) (cond ((uiop:string-prefix-p "#+begin_src lisp" (string-downcase clean-line))
;; Only load blocks that are NOT tangled to src/ or elsewhere
(if (search ":tangle" (string-downcase clean-line)) (if (search ":tangle" (string-downcase clean-line))
(setf in-lisp-block nil) (setf in-lisp-block nil)
(setf in-lisp-block t))) (setf in-lisp-block t)))
@@ -254,21 +161,16 @@ The core "hot-loading" mechanism. It extracts Lisp blocks from an Org file and e
(setf lisp-code (concatenate 'string lisp-code line (string #\Newline)))))))) (setf lisp-code (concatenate 'string lisp-code line (string #\Newline))))))))
(if (= (length lisp-code) 0) (if (= (length lisp-code) 0)
(progn (setf (skill-entry-status entry) :ready) t) ;; Valid empty skill (progn (setf (skill-entry-status entry) :ready) t)
(progn (progn
;; PRE-FLIGHT: Syntax Validation
(multiple-value-bind (valid-p err) (validate-lisp-syntax lisp-code) (multiple-value-bind (valid-p err) (validate-lisp-syntax lisp-code)
(unless valid-p (unless valid-p (error "Syntax Error: ~a" err)))
(error "Syntax Error: ~a" err)))
(harness-log "HARNESS: Jailing skill '~a' in package ~a" skill-base-name pkg-name) (harness-log "HARNESS: Jailing skill '~a' in package ~a" skill-base-name pkg-name)
(unless (find-package pkg-name) (unless (find-package pkg-name)
(let ((new-pkg (make-package pkg-name :use '(:cl)))) (let ((new-pkg (make-package pkg-name :use '(:cl))))
(do-external-symbols (sym (find-package :opencortex)) (shadowing-import sym new-pkg)))) (do-external-symbols (sym (find-package :opencortex)) (shadowing-import sym new-pkg))))
(let ((*read-eval* nil) (*package* (find-package pkg-name))) (let ((*read-eval* nil) (*package* (find-package pkg-name)))
(eval (read-from-string (format nil "(progn ~a)" lisp-code)))) (eval (read-from-string (format nil "(progn ~a)" lisp-code))))
(setf (skill-entry-status entry) :ready) (setf (skill-entry-status entry) :ready)
t))) t)))
(error (c) (error (c)
@@ -277,12 +179,7 @@ The core "hot-loading" mechanism. It extracts Lisp blocks from an Org file and e
(setf (skill-entry-status entry) :failed) (setf (skill-entry-status entry) :failed)
(setf (skill-entry-error-log entry) msg) (setf (skill-entry-error-log entry) msg)
nil))))) nil)))))
#+end_src
** Safe Loading with Timeout (load-skill-with-timeout)
Wraps the skill loader in a thread with a hard timeout to prevent a single malformed skill from hanging the entire boot sequence.
#+begin_src lisp :tangle ../src/skills.lisp
(defun load-skill-with-timeout (filepath timeout-seconds) (defun load-skill-with-timeout (filepath timeout-seconds)
"Loads a skill Org file with a hard execution timeout." "Loads a skill Org file with a hard execution timeout."
(let* ((finished nil) (let* ((finished nil)
@@ -306,12 +203,6 @@ Wraps the skill loader in a thread with a hard timeout to prevent a single malfo
#+end_src #+end_src
** Initializing All Skills (initialize-all-skills) ** Initializing All Skills (initialize-all-skills)
The `initialize-all-skills` function is the unified orchestrator for the system boot sequence. It enforces the **Verification Lock**:
1. **Mandatory Check:** It reads the `MANDATORY_SKILLS` environment variable and ensures every required skill exists in the source directory.
2. **Topological Boot:** It resolves inter-skill dependencies to ensure policies and actuators are loaded in the correct order.
3. **Timed Loading:** Every skill is loaded with a 5-second timeout.
4. **Boot Halt:** If a *mandatory* skill fails to load (e.g., due to a syntax error), the entire system halts with a `BOOT FAILURE` to prevent an unaligned or unsecure state.
#+begin_src lisp :tangle ../src/skills.lisp #+begin_src lisp :tangle ../src/skills.lisp
(defun initialize-all-skills () (defun initialize-all-skills ()
"Scans the directory defined by SKILLS_DIR and hot-loads skills using topological order." "Scans the directory defined by SKILLS_DIR and hot-loads skills using topological order."
@@ -325,12 +216,11 @@ The `initialize-all-skills` function is the unified orchestrator for the system
(return-from initialize-all-skills nil)) (return-from initialize-all-skills nil))
(let ((sorted-files (topological-sort-skills skills-dir))) (let ((sorted-files (topological-sort-skills skills-dir)))
;; MANDATE: Configurable mandatory skills must be present for a safe boot
(let* ((mandatory-env (uiop:getenv "MANDATORY_SKILLS")) (let* ((mandatory-env (uiop:getenv "MANDATORY_SKILLS"))
(mandatory-skills (if mandatory-env (mandatory-skills (if mandatory-env
(mapcar (lambda (s) (string-trim '(#\Space) s)) (mapcar (lambda (s) (string-trim '(#\Space) s))
(uiop:split-string mandatory-env :separator '(#\,))) (uiop:split-string mandatory-env :separator '(#\,)))
'("org-skill-policy" "org-skill-bouncer"))) '("org-skill-policy" "org-skill-bouncer"))))
(dolist (req mandatory-skills) (dolist (req mandatory-skills)
(unless (member req sorted-files :key #'pathname-name :test #'string-equal) (unless (member req sorted-files :key #'pathname-name :test #'string-equal)
(error "BOOT FAILURE: Mandatory skill '~a' not found in skills directory: ~a" req (uiop:native-namestring skills-dir)))) (error "BOOT FAILURE: Mandatory skill '~a' not found in skills directory: ~a" req (uiop:native-namestring skills-dir))))
@@ -348,34 +238,17 @@ The `initialize-all-skills` function is the unified orchestrator for the system
(error "BOOT FAILURE: Mandatory skill '~a' failed to load (Status: ~a)." skill-name status) (error "BOOT FAILURE: Mandatory skill '~a' failed to load (Status: ~a)." skill-name status)
(harness-log "LOADER WARNING: Skill '~a' failed to load." skill-name)))))) (harness-log "LOADER WARNING: Skill '~a' failed to load." skill-name))))))
;; Final Summary
(let ((ready 0) (failed 0)) (let ((ready 0) (failed 0))
(maphash (lambda (k v) (maphash (lambda (k v)
(declare (ignore k)) (declare (ignore k))
(if (eq (skill-entry-status v) :ready) (incf ready) (incf failed)))) (if (eq (skill-entry-status v) :ready) (incf ready) (incf failed)))
*skill-catalog*) *skill-catalog*)
(harness-log " LOADER: Boot Complete. [Ready: ~a] [Failed: ~a]" ready failed) (harness-log " LOADER: Boot Complete. [Ready: ~a] [Failed: ~a]" ready failed)
(harness-log "==================================================") (harness-log "==================================================")
(values ready failed))))) (values ready failed))))))
#+end_src #+end_src
** Toolbelt Prompt Generation (generate-tool-belt-prompt) ** Toolbelt Prompt Generation (generate-tool-belt-prompt)
Every cognitive tool registered by a skill is automatically documented and injected into the LLM system prompt. This ensures that the agent is always aware of its current physical capabilities.
#+begin_src mermaid
flowchart LR
Registry[(Tool Registry)] --> Generator[Prompt Generator]
Generator --> Prompt[Final System Prompt]
subgraph Actuators
ToolA[Shell]
ToolB[Emacs]
ToolC[Grep]
end
ToolA --> Registry
ToolB --> Registry
ToolC --> Registry
#+end_src
#+begin_src lisp :tangle ../src/skills.lisp #+begin_src lisp :tangle ../src/skills.lisp
(defun generate-tool-belt-prompt () (defun generate-tool-belt-prompt ()
"Aggregates all registered cognitive tools into a descriptive prompt." "Aggregates all registered cognitive tools into a descriptive prompt."
@@ -400,8 +273,6 @@ EXAMPLES:
#+end_src #+end_src
** The Default Tool Belt ** The Default Tool Belt
The harness provides a baseline set of cognitive tools that enable core system interaction.
*** The Eval Tool (Internal Inspection) *** The Eval Tool (Internal Inspection)
#+begin_src lisp :tangle ../src/skills.lisp #+begin_src lisp :tangle ../src/skills.lisp
(def-cognitive-tool :eval "Evaluates raw Common Lisp code in the harness image. Use this for complex calculations or internal state inspection." (def-cognitive-tool :eval "Evaluates raw Common Lisp code in the harness image. Use this for complex calculations or internal state inspection."

View File

@@ -128,7 +128,6 @@
(dolist (line lines) (dolist (line lines)
(let ((clean-line (string-trim '(#\Space #\Tab #\Return) line))) (let ((clean-line (string-trim '(#\Space #\Tab #\Return) line)))
(cond ((uiop:string-prefix-p "#+begin_src lisp" (string-downcase clean-line)) (cond ((uiop:string-prefix-p "#+begin_src lisp" (string-downcase clean-line))
;; Only load blocks that are NOT tangled to src/ or elsewhere
(if (search ":tangle" (string-downcase clean-line)) (if (search ":tangle" (string-downcase clean-line))
(setf in-lisp-block nil) (setf in-lisp-block nil)
(setf in-lisp-block t))) (setf in-lisp-block t)))
@@ -140,21 +139,16 @@
(setf lisp-code (concatenate 'string lisp-code line (string #\Newline)))))))) (setf lisp-code (concatenate 'string lisp-code line (string #\Newline))))))))
(if (= (length lisp-code) 0) (if (= (length lisp-code) 0)
(progn (setf (skill-entry-status entry) :ready) t) ;; Valid empty skill (progn (setf (skill-entry-status entry) :ready) t)
(progn (progn
;; PRE-FLIGHT: Syntax Validation
(multiple-value-bind (valid-p err) (validate-lisp-syntax lisp-code) (multiple-value-bind (valid-p err) (validate-lisp-syntax lisp-code)
(unless valid-p (unless valid-p (error "Syntax Error: ~a" err)))
(error "Syntax Error: ~a" err)))
(harness-log "HARNESS: Jailing skill '~a' in package ~a" skill-base-name pkg-name) (harness-log "HARNESS: Jailing skill '~a' in package ~a" skill-base-name pkg-name)
(unless (find-package pkg-name) (unless (find-package pkg-name)
(let ((new-pkg (make-package pkg-name :use '(:cl)))) (let ((new-pkg (make-package pkg-name :use '(:cl))))
(do-external-symbols (sym (find-package :opencortex)) (shadowing-import sym new-pkg)))) (do-external-symbols (sym (find-package :opencortex)) (shadowing-import sym new-pkg))))
(let ((*read-eval* nil) (*package* (find-package pkg-name))) (let ((*read-eval* nil) (*package* (find-package pkg-name)))
(eval (read-from-string (format nil "(progn ~a)" lisp-code)))) (eval (read-from-string (format nil "(progn ~a)" lisp-code))))
(setf (skill-entry-status entry) :ready) (setf (skill-entry-status entry) :ready)
t))) t)))
(error (c) (error (c)
@@ -197,12 +191,11 @@
(return-from initialize-all-skills nil)) (return-from initialize-all-skills nil))
(let ((sorted-files (topological-sort-skills skills-dir))) (let ((sorted-files (topological-sort-skills skills-dir)))
;; MANDATE: Configurable mandatory skills must be present for a safe boot
(let* ((mandatory-env (uiop:getenv "MANDATORY_SKILLS")) (let* ((mandatory-env (uiop:getenv "MANDATORY_SKILLS"))
(mandatory-skills (if mandatory-env (mandatory-skills (if mandatory-env
(mapcar (lambda (s) (string-trim '(#\Space) s)) (mapcar (lambda (s) (string-trim '(#\Space) s))
(uiop:split-string mandatory-env :separator '(#\,))) (uiop:split-string mandatory-env :separator '(#\,)))
'("org-skill-policy" "org-skill-bouncer"))) '("org-skill-policy" "org-skill-bouncer"))))
(dolist (req mandatory-skills) (dolist (req mandatory-skills)
(unless (member req sorted-files :key #'pathname-name :test #'string-equal) (unless (member req sorted-files :key #'pathname-name :test #'string-equal)
(error "BOOT FAILURE: Mandatory skill '~a' not found in skills directory: ~a" req (uiop:native-namestring skills-dir)))) (error "BOOT FAILURE: Mandatory skill '~a' not found in skills directory: ~a" req (uiop:native-namestring skills-dir))))
@@ -220,15 +213,14 @@
(error "BOOT FAILURE: Mandatory skill '~a' failed to load (Status: ~a)." skill-name status) (error "BOOT FAILURE: Mandatory skill '~a' failed to load (Status: ~a)." skill-name status)
(harness-log "LOADER WARNING: Skill '~a' failed to load." skill-name)))))) (harness-log "LOADER WARNING: Skill '~a' failed to load." skill-name))))))
;; Final Summary
(let ((ready 0) (failed 0)) (let ((ready 0) (failed 0))
(maphash (lambda (k v) (maphash (lambda (k v)
(declare (ignore k)) (declare (ignore k))
(if (eq (skill-entry-status v) :ready) (incf ready) (incf failed)))) (if (eq (skill-entry-status v) :ready) (incf ready) (incf failed)))
*skill-catalog*) *skill-catalog*)
(harness-log " LOADER: Boot Complete. [Ready: ~a] [Failed: ~a]" ready failed) (harness-log " LOADER: Boot Complete. [Ready: ~a] [Failed: ~a]" ready failed)
(harness-log "==================================================") (harness-log "==================================================")
(values ready failed))))) (values ready failed))))))
(defun generate-tool-belt-prompt () (defun generate-tool-belt-prompt ()
"Aggregates all registered cognitive tools into a descriptive prompt." "Aggregates all registered cognitive tools into a descriptive prompt."