Files
passepartout/org/core-defpackage.org
Amr Gharbeia ce90fd3e72
Some checks failed
Deploy (Gitea) / deploy (push) Has been cancelled
fix: HITL functions now properly loaded, define missing proto-get
Root cause chain:
1. proto-get was used throughout the pipeline but never defined — added
   to core-communication.org as a keyword-normalizing getf wrapper.
2. security-dispatcher.lisp was loaded by skill-initialize-all into a
   separate package, making HITL functions invisible to :passepartout.
   Fixed by adding to ASDF component list and excluding from skill loader.
3. org-id-generate was referenced from hitl-create but lives in an
   unexported skill package — replaced with uuid:make-v4-uuid.
4. uiop:string-prefix-p was called with :test keyword argument it does
   not accept — replaced with string-downcase normalization on both sides.

Also:
- Export hitl-create, hitl-approve, hitl-deny, hitl-handle-message,
  stimulus-inject from :passepartout for REPL accessibility.
2026-05-03 14:21:08 -04:00

298 lines
11 KiB
Org Mode

#+TITLE: Core: Package Definition (core-defpackage.org)
#+AUTHOR: Agent
#+FILETAGS: :passepartout:core:defpackage:
#+STARTUP: content
#+PROPERTY: header-args:lisp :tangle ../lisp/core-defpackage.lisp
* Overview: Architectural Intent
~package.lisp~ defines two things: the public API of the ~passepartout~ package (the export list), and the implementation of low-level utility functions and global state that don't belong in a specific pipeline stage or skill.
The export list is the contract between the harness and all skills. Every function exported here is accessible to every skill via ~use-package~. Adding a symbol here is an API commitment; removing one is a breaking change.
The implementation section includes:
- ~plist-get~ — robust plist accessor used everywhere in the pipeline
- Logging state (~*log-buffer*~, ~*log-lock*~) — bounded ring buffer for LLM context
- Skill registry (~*skill-registry*~, ~defskill~) — all loaded skills live here
- Cognitive tool registry (~*cognitive-tool-registry*~, ~def-cognitive-tool~, ~cognitive-tool-prompt~)
- Telemetry tracking (~*telemetry-table*~, ~telemetry-track~) — performance metrics per skill
- Debugger hook — replaces raw SBCL debugger with a friendly error message
* Implementation
** Package Definition and Export List
The package definition. All public symbols are exported here.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defpackage :passepartout
(:use :cl)
(:export
#:frame-message
#:read-framed-message
#:PROTO-GET
#:LIST-OBJECTS-WITH-ATTRIBUTE
#:COSINE-SIMILARITY
#:VAULT-MASK-STRING
#:*VAULT-MEMORY*
#:parse-message
#:make-hello-message
#:validate-communication-protocol-schema
#:start-daemon
#:stop-daemon
#:log-message
#:main
#:doctor-run-all
#:doctor-main
#:doctor-check-dependencies
#:doctor-check-env
#:register-provider
#:system-ready-p
#:run-setup-wizard
#:skill-gateway-register
#:skill-gateway-link
#:gateway-manager-main
#:ingest-ast
#:memory-object-get
#:list-objects-by-type
#:org-id-new
#:*memory-store*
#:*history-store*
#:memory-object
#:make-memory-object
#:memory-object-id
#:memory-object-type
#:memory-object-attributes
#:memory-object-parent-id
#:memory-object-children
#:memory-object-version
#:memory-object-last-sync
#:memory-object-vector
#:memory-object-content
#:memory-object-hash
#:memory-object-scope
#:snapshot-memory
#:rollback-memory
#:context-query-store
#:context-get-active-projects
#:context-get-recent-completed-tasks
#:context-list-all-skills
#:context-get-skill-source
#:context-get-system-logs
#:context-resolve-path
#:context-get-skill-telemetry
#:telemetry-track
#:context-assemble-global-awareness
#:process-signal
#:loop-process
#:perceive-gate
#:probabilistic-gate
#:consensus-gate
#:act-gate
#:reason-gate
#:dispatch-gate
#:register-pre-reason-handler
#:inject-stimulus
#:stimulus-inject
#:hitl-create
#:hitl-approve
#:hitl-deny
#:hitl-handle-message
#:actuator-initialize
#:dispatch-action
#:register-actuator
#:load-skill-from-org
#:skill-initialize-all
#:load-skill-with-timeout
#:topological-sort-skills
#:validate-lisp-syntax
#:defskill
#:*skill-registry*
#:skill
#:skill-name
#:skill-priority
#:skill-dependencies
#:skill-trigger-fn
#:skill-probabilistic-prompt
#:skill-deterministic-fn
#:def-cognitive-tool
#:*cognitive-tool-registry*
#:verify-git-clean-p
#:engineering-standards-verify-lisp
#:engineering-standards-format-lisp
#:literate-check-block-balance
#:check-tangle-sync
#:*tangle-targets*
#:utils-org-read-file
#:utils-org-write-file
#:utils-org-add-headline
#:utils-org-set-property
#:utils-org-set-todo
#:utils-org-find-headline-by-id
#:utils-org-find-headline-by-title
#:utils-org-generate-id
#:utils-org-id-format
#:utils-org-ast-to-org
#:utils-org-modify
#:utils-lisp-validate
#:utils-lisp-check-structural
#:utils-lisp-check-syntactic
#:utils-lisp-check-semantic
#:utils-lisp-eval
#:utils-lisp-format
#:utils-lisp-list-definitions
#:utils-lisp-structural-extract
#:utils-lisp-structural-wrap
#:utils-lisp-structural-inject
#:utils-lisp-structural-slurp
#:utils-lisp-register
#:get-oc-config-dir
#:prompt-for
#:save-secret
#:get-tool-permission
#:set-tool-permission
#:check-tool-permission-gate
#:cognitive-tool
#:cognitive-tool-name
#:cognitive-tool-description
#:cognitive-tool-parameters
#:cognitive-tool-guard
#:cognitive-tool-body
#:*emacs-clients*
#:*clients-lock*
#:register-emacs-client
#:unregister-emacs-client
#:ask-probabilistic
#:register-probabilistic-backend
#:distill-prompt
#:*probabilistic-backends*
#:*provider-cascade*
#:vault-get-secret
#:vault-set-secret
#:memory-objects-by-attribute
#:deterministic-verify
#:find-headline-missing-id))
#+end_src
** Package Implementation
The package implementation section defines the low-level utilities and global state that are shared across all harness components and skills.
*** Robust plist access (plist-get)
Retrieves a value from a plist, checking both upper and lowercase keyword variants. This is needed because different components use different keyword conventions.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(in-package :passepartout)
(defun plist-get (plist key)
"Robust plist accessor — checks both :KEY and :key variants."
(let* ((s (string key))
(up (intern (string-upcase s) :keyword))
(dn (intern (string-downcase s) :keyword)))
(or (getf plist up) (getf plist dn))))
#+end_src
*** Logging state
The harness maintains a bounded ring buffer of log messages for inclusion in LLM context. Access is thread-safe via a lock.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defvar *log-buffer* nil)
(defvar *log-lock* (bordeaux-threads:make-lock "log-messages-lock"))
(defvar *log-limit* 100)
#+end_src
*** Skill registry
The global registry of all loaded skills. This is the authoritative list that the deterministic engine iterates.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defvar *skill-registry* (make-hash-table :test 'equal)
"Global registry of all loaded skills.")
#+end_src
*** Skill telemetry
Tracks execution metrics per skill (count, duration, failures) for diagnostics and performance analysis.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defvar *telemetry-table* (make-hash-table :test 'equal))
(defvar *telemetry-lock* (bordeaux-threads:make-lock "harness-telemetry-lock"))
(defun telemetry-track (skill-name duration status)
"Updates performance metrics for a skill. STATUS is :success or :rejected."
(when skill-name
(bordeaux-threads:with-lock-held (*telemetry-lock*)
(let ((entry (or (gethash skill-name *telemetry-table*) (list :executions 0 :total-time 0 :failures 0))))
(incf (getf entry :executions))
(incf (getf entry :total-time) duration)
(when (eq status :rejected) (incf (getf entry :failures)))
(setf (gethash skill-name *telemetry-table*) entry)))))
#+end_src
*** Cognitive tool registry
Tools that the LLM can invoke are registered here. Each tool has a name, description, parameters, optional guard, and implementation body. The ~def-cognitive-tool~ macro handles registration. ~cognitive-tool-prompt~ serialises the registry into the LLM's system prompt.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defvar *cognitive-tool-registry* (make-hash-table :test 'equal))
#+end_src
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defstruct cognitive-tool
name
description
parameters
guard
body)
#+end_src
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defmacro def-cognitive-tool (name description parameters &key guard body)
"Registers a cognitive tool. PARAMETERS is a list of plists, one per parameter."
`(setf (gethash (string-downcase (string ',name)) *cognitive-tool-registry*)
(make-cognitive-tool :name (string-downcase (string ',name))
:description ,description
:parameters ',parameters
:guard ,guard
:body ,body)))
#+end_src
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defun cognitive-tool-prompt ()
"Serialises all registered tools into a prompt string for the LLM."
(let ((descriptions nil))
(maphash (lambda (k tool)
(declare (ignore k))
(push (format nil "- ~a: ~a~% Parameters: ~a~%"
(cognitive-tool-name tool)
(cognitive-tool-description tool)
(cognitive-tool-parameters tool))
descriptions))
*cognitive-tool-registry*)
(if descriptions
(format nil "Available tools:~%~a" (apply #'concatenate 'string (sort descriptions #'string<)))
"No tools registered.")))
#+end_src
*** Centralized logging (log-message)
Thread-safe logging function that writes to both the ring buffer (for LLM context) and stdout (for the user). Bounded by ~*log-limit*~.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(defun log-message (msg &rest args)
"Centralized, thread-safe logging for the harness."
(let ((formatted-msg (apply #'format nil msg args)))
(bordeaux-threads:with-lock-held (*log-lock*)
(push formatted-msg *log-buffer*)
(when (> (length *log-buffer*) *log-limit*)
(setq *log-buffer* (subseq *log-buffer* 0 *log-limit*))))
(format t "~a~%" formatted-msg)
(finish-output)))
#+end_src
*** Debugger hook
Friendly error handler that replaces the raw SBCL debugger with a diagnostic message. This prevents the agent from entering the debugger on unhandled conditions.
#+begin_src lisp :tangle ../lisp/core-defpackage.lisp
(setf *debugger-hook* (lambda (condition hook)
"Friendly error handler - shows diagnostic message instead of raw debugger."
(declare (ignore hook))
(format t "~%")
(format t "┌─────────────────────────────────────────────┐~%")
(format t "│ ERROR: ~A~%" (type-of condition))
(format t "│~%")
(format t "│ Run: passepartout doctor~%")
(format t "│ For system diagnostics~%")
(format t "└─────────────────────────────────────────────┘~%")
(format t "~%")
(format t "Details: ~A~%" condition)
(finish-output)
(uiop:quit 1)))
#+end_src