REFAC: Refactored perceive stage and relocated telemetry

This commit is contained in:
2026-04-13 17:07:01 -04:00
parent 7b56a46500
commit 222a231d40
5 changed files with 111 additions and 29 deletions

View File

@@ -64,6 +64,7 @@ flowchart TD
#:context-get-system-logs #:context-get-system-logs
#:context-resolve-path #:context-resolve-path
#:context-get-skill-telemetry #:context-get-skill-telemetry
#:harness-track-telemetry
#:context-assemble-global-awareness #:context-assemble-global-awareness
;; --- Reactive Signal Pipeline --- ;; --- Reactive Signal Pipeline ---
@@ -149,6 +150,21 @@ The harness maintains a thread-safe circular log buffer to provide context for d
(defvar *telemetry-lock* (bt:make-lock "harness-telemetry-lock")) (defvar *telemetry-lock* (bt:make-lock "harness-telemetry-lock"))
#+end_src #+end_src
** Telemetry Implementation
The system tracks the performance and reliability of individual skills. This logic is currently preserved in the package layer for future expansion into a dedicated telemetry skill.
#+begin_src lisp :tangle ../src/package.lisp
(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*)
(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)
(when (eq status :rejected) (incf (getf entry :failures)))
(setf (gethash skill-name *skill-telemetry*) entry)))))
#+end_src
** Cognitive Tool Registry ** Cognitive Tool Registry
The Tool Registry allows the agent to interact with the physical world. Every tool must define a guard (for security) and a body (for execution). The Tool Registry allows the agent to interact with the physical world. Every tool must define a guard (for security) and a body (for execution).

View File

@@ -5,43 +5,78 @@
* Stage 1: Perceive (perceive.lisp) * Stage 1: Perceive (perceive.lisp)
** Architectural Intent: Sensory Ingestion ** Architectural Intent: Sensory Ingestion
The Perceive stage is responsible for data normalization and sensory intake. It takes raw stimuli (from TCP sockets, Signal, or Heartbeats) and updates the global Memory graph. The Perceive stage is the "sensory cortex" of the Org-Agent. It takes raw stimuli from the outside world (keyboard events, chat messages, heartbeats, or system interrupts) and normalizes them into internal **Signals**.
** Async Sensor Routing
To prevent blocking the main pipeline, certain sensors (like user commands or chat messages) are processed asynchronously in their own threads.
#+begin_src lisp :tangle ../src/perceive.lisp #+begin_src lisp :tangle ../src/perceive.lisp
(in-package :org-agent) (in-package :org-agent)
(defun harness-track-telemetry (skill-name duration status) (defvar *async-sensors* '(:chat-message :delegation :user-command)
"Updates performance metrics for a specific skill." "List of sensors that should be processed asynchronously to avoid blocking gateways.")
(when skill-name (bt:with-lock-held (*telemetry-lock*) #+end_src
(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)
(when (eq status :rejected) (incf (getf entry :failures))) (setf (gethash skill-name *skill-telemetry*) entry)))))
** Foveal Focus State
The system tracks the user's current point of interaction to provide context to the reasoning engine.
#+begin_src lisp :tangle ../src/perceive.lisp
(defvar *foveal-focus-id* nil
"The Org ID of the node the user is currently interacting with.")
#+end_src
** Stimulus Injection
The entry point for raw messages. It determines if the signal should be processed synchronously or asynchronously.
#+begin_src lisp :tangle ../src/perceive.lisp
(defun inject-stimulus (raw-message &key stream (depth 0)) (defun inject-stimulus (raw-message &key stream (depth 0))
"Enqueues a raw message into the reactive signal pipeline." "Enqueues a raw message into the reactive signal pipeline."
(let* ((payload (getf raw-message :payload)) (let* ((payload (getf raw-message :payload))
(sensor (getf payload :sensor)) (sensor (getf payload :sensor))
(async-p (or (getf payload :async-p) (member sensor '(:chat-message :delegation :user-command))))) (async-p (or (getf payload :async-p) (member sensor *async-sensors*))))
(when stream (setf (getf raw-message :reply-stream) stream)) (when stream (setf (getf raw-message :reply-stream) stream))
(if async-p (bt:make-thread (lambda () (restart-case (handler-bind ((error (lambda (c) (harness-log "ASYNC ERROR: ~a" c) (invoke-restart 'skip-event)))) (if async-p
(process-signal raw-message)) (skip-event () nil))) :name "org-agent-async-task") (bt:make-thread
(restart-case (handler-bind ((error (lambda (c) (harness-log "SYSTEM ERROR: ~a" c) (invoke-restart 'skip-event)))) (process-signal raw-message)) (lambda ()
(restart-case (handler-bind ((error (lambda (c) (harness-log "ASYNC ERROR: ~a" c) (invoke-restart 'skip-event))))
(process-signal raw-message))
(skip-event () nil)))
:name "org-agent-async-task")
(restart-case (handler-bind ((error (lambda (c) (harness-log "SYSTEM ERROR: ~a" c) (invoke-restart 'skip-event))))
(process-signal raw-message))
(skip-event () (harness-log "SYSTEM RECOVERY: Stimulus dropped.~%")))))) (skip-event () (harness-log "SYSTEM RECOVERY: Stimulus dropped.~%"))))))
#+end_src
** The Perceive Gate
The initial stage of the metabolic loop. It logs the signal, performs selective memory snapshots, and updates the Memory graph based on incoming AST updates.
#+begin_src lisp :tangle ../src/perceive.lisp
(defun perceive-gate (signal) (defun perceive-gate (signal)
"Initial processing: Normalizes raw stimuli and updates memory." "Initial processing: Normalizes raw stimuli and updates memory."
(let* ((payload (getf signal :payload)) (let* ((payload (getf signal :payload))
(type (getf signal :type)) (type (getf signal :type))
(sensor (getf payload :sensor))) (sensor (getf payload :sensor)))
(harness-log "GATE [Perceive]: ~a (~a)" type (or sensor "no-sensor")) (harness-log "GATE [Perceive]: ~a (~a)" type (or sensor "no-sensor"))
(snapshot-memory)
(cond ((eq type :EVENT) (cond ((eq type :EVENT)
(case sensor (case sensor
(:buffer-update (let ((ast (getf payload :ast))) (when ast (ingest-ast ast)))) (:buffer-update
(:point-update (let ((element (getf payload :element))) (when element (ingest-ast element)))) (let ((ast (getf payload :ast)))
(:interrupt (bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t))))) (when ast
(snapshot-memory)
(ingest-ast ast))))
(:point-update
(let ((element (getf payload :element)))
(when element
(snapshot-memory)
(setf *foveal-focus-id* (ignore-errors (getf element :id)))
(ingest-ast element))))
(:interrupt
(bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t)))))
((eq type :RESPONSE) ((eq type :RESPONSE)
(harness-log "GATE [Perceive]: Act Result -> ~a" (getf payload :status)))) (harness-log "GATE [Perceive]: Act Result -> ~a" (getf payload :status))))
(setf (getf signal :status) :perceived) (setf (getf signal :status) :perceived)
(setf (getf signal :foveal-focus) *foveal-focus-id*)
signal)) signal))
#+end_src #+end_src

View File

@@ -36,6 +36,9 @@ You are strictly forbidden from considering a task complete without updating `gt
** 8. Configuration Externalization (Environment-Driven) ** 8. Configuration Externalization (Environment-Driven)
Source code MUST be strictly free of hardcoded configuration values (e.g., ports, rhythms, timeouts). All such values must be extracted to the environment (via `.env`) and documented in `.env.example`. This ensures portability and security. Source code MUST be strictly free of hardcoded configuration values (e.g., ports, rhythms, timeouts). All such values must be extracted to the environment (via `.env`) and documented in `.env.example`. This ensures portability and security.
** 9. Literate-Only Modification (The Tangle Mandate)
You are strictly forbidden from modifying generated source code files (e.g., `.lisp`, `.py`, `.el`) directly. All changes MUST be made within the corresponding Literate Org file and then tangled to the source. Direct modification of source code is only permitted with explicit user authorization.
* Phase B: Blueprint (PROTOCOL) * Phase B: Blueprint (PROTOCOL)
:PROPERTIES: :PROPERTIES:
:STATUS: SIGNED :STATUS: SIGNED

View File

@@ -43,6 +43,7 @@
#:context-get-system-logs #:context-get-system-logs
#:context-resolve-path #:context-resolve-path
#:context-get-skill-telemetry #:context-get-skill-telemetry
#:harness-track-telemetry
#:context-assemble-global-awareness #:context-assemble-global-awareness
;; --- Reactive Signal Pipeline --- ;; --- Reactive Signal Pipeline ---
@@ -113,6 +114,16 @@
(defvar *skill-telemetry* (make-hash-table :test 'equal)) (defvar *skill-telemetry* (make-hash-table :test 'equal))
(defvar *telemetry-lock* (bt:make-lock "harness-telemetry-lock")) (defvar *telemetry-lock* (bt: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*)
(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)
(when (eq status :rejected) (incf (getf entry :failures)))
(setf (gethash skill-name *skill-telemetry*) entry)))))
(defvar *cognitive-tools* (make-hash-table :test 'equal)) (defvar *cognitive-tools* (make-hash-table :test 'equal))
(defstruct cognitive-tool (defstruct cognitive-tool

View File

@@ -1,21 +1,26 @@
(in-package :org-agent) (in-package :org-agent)
(defun harness-track-telemetry (skill-name duration status) (defvar *async-sensors* '(:chat-message :delegation :user-command)
"Updates performance metrics for a specific skill." "List of sensors that should be processed asynchronously to avoid blocking gateways.")
(when skill-name (bt:with-lock-held (*telemetry-lock*)
(let ((entry (or (gethash skill-name *skill-telemetry*) (list :executions 0 :total-time 0 :failures 0)))) (defvar *foveal-focus-id* nil
(incf (getf entry :executions)) (incf (getf entry :total-time) duration) "The Org ID of the node the user is currently interacting with.")
(when (eq status :rejected) (incf (getf entry :failures))) (setf (gethash skill-name *skill-telemetry*) entry)))))
(defun inject-stimulus (raw-message &key stream (depth 0)) (defun inject-stimulus (raw-message &key stream (depth 0))
"Enqueues a raw message into the reactive signal pipeline." "Enqueues a raw message into the reactive signal pipeline."
(let* ((payload (getf raw-message :payload)) (let* ((payload (getf raw-message :payload))
(sensor (getf payload :sensor)) (sensor (getf payload :sensor))
(async-p (or (getf payload :async-p) (member sensor '(:chat-message :delegation :user-command))))) (async-p (or (getf payload :async-p) (member sensor *async-sensors*))))
(when stream (setf (getf raw-message :reply-stream) stream)) (when stream (setf (getf raw-message :reply-stream) stream))
(if async-p (bt:make-thread (lambda () (restart-case (handler-bind ((error (lambda (c) (harness-log "ASYNC ERROR: ~a" c) (invoke-restart 'skip-event)))) (if async-p
(process-signal raw-message)) (skip-event () nil))) :name "org-agent-async-task") (bt:make-thread
(restart-case (handler-bind ((error (lambda (c) (harness-log "SYSTEM ERROR: ~a" c) (invoke-restart 'skip-event)))) (process-signal raw-message)) (lambda ()
(restart-case (handler-bind ((error (lambda (c) (harness-log "ASYNC ERROR: ~a" c) (invoke-restart 'skip-event))))
(process-signal raw-message))
(skip-event () nil)))
:name "org-agent-async-task")
(restart-case (handler-bind ((error (lambda (c) (harness-log "SYSTEM ERROR: ~a" c) (invoke-restart 'skip-event))))
(process-signal raw-message))
(skip-event () (harness-log "SYSTEM RECOVERY: Stimulus dropped.~%")))))) (skip-event () (harness-log "SYSTEM RECOVERY: Stimulus dropped.~%"))))))
(defun perceive-gate (signal) (defun perceive-gate (signal)
@@ -24,13 +29,25 @@
(type (getf signal :type)) (type (getf signal :type))
(sensor (getf payload :sensor))) (sensor (getf payload :sensor)))
(harness-log "GATE [Perceive]: ~a (~a)" type (or sensor "no-sensor")) (harness-log "GATE [Perceive]: ~a (~a)" type (or sensor "no-sensor"))
(snapshot-memory)
(cond ((eq type :EVENT) (cond ((eq type :EVENT)
(case sensor (case sensor
(:buffer-update (let ((ast (getf payload :ast))) (when ast (ingest-ast ast)))) (:buffer-update
(:point-update (let ((element (getf payload :element))) (when element (ingest-ast element)))) (let ((ast (getf payload :ast)))
(:interrupt (bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t))))) (when ast
(snapshot-memory)
(ingest-ast ast))))
(:point-update
(let ((element (getf payload :element)))
(when element
(snapshot-memory)
(setf *foveal-focus-id* (ignore-errors (getf element :id)))
(ingest-ast element))))
(:interrupt
(bt:with-lock-held (*interrupt-lock*) (setf *interrupt-flag* t)))))
((eq type :RESPONSE) ((eq type :RESPONSE)
(harness-log "GATE [Perceive]: Act Result -> ~a" (getf payload :status)))) (harness-log "GATE [Perceive]: Act Result -> ~a" (getf payload :status))))
(setf (getf signal :status) :perceived) (setf (getf signal :status) :perceived)
(setf (getf signal :foveal-focus) *foveal-focus-id*)
signal)) signal))