feat: implement Foveal-Peripheral vision model and Org renderer
This commit is contained in:
@@ -80,7 +80,7 @@ Reads the raw literate source of a specific skill. This is crucial for "System 2
|
|||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Kernel Logs (context-get-system-logs)
|
** Kernel Logs (context-get-system-logs)
|
||||||
Retrieves the most recent system logs, providing temporal context to the LLM.
|
Retrieves the most recent lines from the kernel's internal log.
|
||||||
|
|
||||||
#+begin_src lisp :tangle ../src/context.lisp
|
#+begin_src lisp :tangle ../src/context.lisp
|
||||||
(defun context-get-system-logs (&optional (limit 20))
|
(defun context-get-system-logs (&optional (limit 20))
|
||||||
@@ -98,19 +98,33 @@ Provides execution stats for a specific skill.
|
|||||||
(bt:with-lock-held (*telemetry-lock*) (gethash (string-downcase skill-name) *skill-telemetry*)))
|
(bt:with-lock-held (*telemetry-lock*) (gethash (string-downcase skill-name) *skill-telemetry*)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Sparse Trees (context-filter-sparse-tree)
|
** AST to Org Rendering (context-render-to-org)
|
||||||
Prunes the Org AST to show only specific nodes and their ancestors, creating a "skeleton" view that fits within LLM context limits.
|
Transforms the internal Object Store structures back into a human-readable (and LLM-readable) Org-mode string. It supports depth-based indentation and content suppression for peripheral nodes.
|
||||||
|
|
||||||
#+begin_src lisp :tangle ../src/context.lisp
|
#+begin_src lisp :tangle ../src/context.lisp
|
||||||
(defun context-filter-sparse-tree (ast predicate)
|
(defun context-render-to-org (obj &key (depth 1) (foveal-id nil))
|
||||||
"Prunes an AST to show only nodes matching a predicate and their ancestors."
|
"Recursively renders an org-object and its children to an Org string."
|
||||||
(if (listp ast)
|
(let* ((is-foveal (equal (org-object-id obj) foveal-id))
|
||||||
(let* ((contents (getf ast :contents))
|
(title (or (getf (org-object-attributes obj) :TITLE) "Untitled"))
|
||||||
(filtered-contents (remove-if #'null (mapcar (lambda (c) (context-filter-sparse-tree c predicate)) contents))))
|
(id (org-object-id obj))
|
||||||
(if (or (funcall predicate ast) (not (null filtered-contents)))
|
(content (org-object-content obj))
|
||||||
(let ((new-ast (copy-list ast))) (setf (getf new-ast :contents) filtered-contents) new-ast)
|
(children (org-object-children obj))
|
||||||
nil))
|
(stars (make-string depth :initial-element #\*))
|
||||||
nil))
|
(output (format nil "~a ~a~%:PROPERTIES:~%:ID: ~a~%:END:~%" stars title id)))
|
||||||
|
|
||||||
|
;; Only include content if this is the foveal focus
|
||||||
|
(when (and is-foveal content)
|
||||||
|
(setf output (concatenate 'string output content (string #\Newline))))
|
||||||
|
|
||||||
|
;; Recursively render children
|
||||||
|
(dolist (child-id children)
|
||||||
|
(let ((child-obj (lookup-object child-id)))
|
||||||
|
(when child-obj
|
||||||
|
(setf output (concatenate 'string output
|
||||||
|
(context-render-to-org child-obj
|
||||||
|
:depth (1+ depth)
|
||||||
|
:foveal-id foveal-id))))))
|
||||||
|
output))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Path Resolution (context-resolve-path)
|
** Path Resolution (context-resolve-path)
|
||||||
@@ -130,20 +144,20 @@ Expands environment variables (like `$HOME`) within path strings.
|
|||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Global Awareness (context-assemble-global-awareness)
|
** Global Awareness (context-assemble-global-awareness)
|
||||||
The primary "peripheral vision" generator. It produces the skeletal overview of the Memex that is prepended to LLM prompts.
|
The primary context generator. It identifies active projects and the current foveal focus, then assembles a pruned Org-mode view of the Memex.
|
||||||
|
|
||||||
#+begin_src lisp :tangle ../src/context.lisp
|
#+begin_src lisp :tangle ../src/context.lisp
|
||||||
(defun context-assemble-global-awareness ()
|
(defun context-assemble-global-awareness (&optional signal)
|
||||||
"Produces a high-level skeletal outline of the current Object Store for the LLM."
|
"Produces a high-level skeletal outline of the current Object Store for the LLM."
|
||||||
(let ((projects (context-get-active-projects))
|
(let* ((payload (when signal (getf signal :payload)))
|
||||||
(output "GLOBAL MEMEX AWARENESS (Peripheral Vision):
|
(foveal-id (when payload (getf payload :target-id)))
|
||||||
|
(projects (context-get-active-projects))
|
||||||
|
(output "GLOBAL MEMEX AWARENESS (Peripheral Vision):
|
||||||
"))
|
"))
|
||||||
(if projects
|
(if projects
|
||||||
(dolist (project projects)
|
(dolist (project projects)
|
||||||
(setf output (concatenate 'string output
|
(setf output (concatenate 'string output
|
||||||
(format nil "- PROJECT: ~a (ID: ~a)~%"
|
(context-render-to-org project :foveal-id foveal-id))))
|
||||||
(getf (org-object-attributes project) :TITLE)
|
|
||||||
(org-object-id project)))))
|
|
||||||
(setf output (concatenate 'string output "No active projects found.~%")))
|
(setf output (concatenate 'string output "No active projects found.~%")))
|
||||||
output))
|
output))
|
||||||
#+end_src
|
#+end_src
|
||||||
@@ -205,3 +219,41 @@ Identifies the top-k most semantically related objects in the entire store by co
|
|||||||
(maphash (lambda (id obj) (let ((vec (org-object-vector obj))) (when vec (push (cons (cosine-similarity query-vector vec) obj) similarities)))) *object-store*)
|
(maphash (lambda (id obj) (let ((vec (org-object-vector obj))) (when vec (push (cons (cosine-similarity query-vector vec) obj) similarities)))) *object-store*)
|
||||||
(let ((sorted (sort similarities #'> :key #'car))) (subseq sorted 0 (min top-k (length sorted))))))
|
(let ((sorted (sort similarities #'> :key #'car))) (subseq sorted 0 (min top-k (length sorted))))))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
* Phase E: Chaos (Verification)
|
||||||
|
Verification of the peripheral vision extraction and rendering logic.
|
||||||
|
|
||||||
|
#+begin_src lisp :tangle ../tests/peripheral-vision-tests.lisp
|
||||||
|
(defpackage :org-agent-peripheral-vision-tests
|
||||||
|
(:use :cl :fiveam :org-agent))
|
||||||
|
(in-package :org-agent-peripheral-vision-tests)
|
||||||
|
|
||||||
|
(def-suite vision-suite
|
||||||
|
:description "Verification of Foveal-Peripheral context model.")
|
||||||
|
(in-suite vision-suite)
|
||||||
|
|
||||||
|
(test test-foveal-rendering
|
||||||
|
"Verify that the foveal target is rendered with content, while siblings are skeletal."
|
||||||
|
(clrhash org-agent::*object-store*)
|
||||||
|
(let* ((ast '(:type :HEADLINE :properties (:ID "proj-root" :TITLE "Project" :TAGS "project")
|
||||||
|
:contents ((:type :HEADLINE :properties (:ID "node-foveal" :TITLE "Foveal Node")
|
||||||
|
:raw-content "FOVEAL CONTENT" :contents nil)
|
||||||
|
(:type :HEADLINE :properties (:ID "node-peripheral" :TITLE "Peripheral Node")
|
||||||
|
:raw-content "PERIPHERAL CONTENT" :contents nil)))))
|
||||||
|
(ingest-ast ast)
|
||||||
|
(let ((output (context-assemble-global-awareness (list :payload (list :target-id "node-foveal")))))
|
||||||
|
;; Foveal node should have its content
|
||||||
|
(is (search "FOVEAL CONTENT" output))
|
||||||
|
;; Peripheral node should be skeletal (only title/ID)
|
||||||
|
(is (search "* Peripheral Node" output))
|
||||||
|
(is (not (search "PERIPHERAL CONTENT" output))))))
|
||||||
|
|
||||||
|
(test test-awareness-budget
|
||||||
|
"Verify that context-assemble-global-awareness handles multiple projects."
|
||||||
|
(clrhash org-agent::*object-store*)
|
||||||
|
(ingest-ast '(:type :HEADLINE :properties (:ID "p1" :TITLE "Project 1" :TAGS "project") :contents nil))
|
||||||
|
(ingest-ast '(:type :HEADLINE :properties (:ID "p2" :TITLE "Project 2" :TAGS "project") :contents nil))
|
||||||
|
(let ((output (context-assemble-global-awareness)))
|
||||||
|
(is (search "Project 1" output))
|
||||||
|
(is (search "Project 2" output))))
|
||||||
|
#+end_src
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
:components ((:module "tests"
|
:components ((:module "tests"
|
||||||
:components ((:file "oacp-tests")
|
:components ((:file "oacp-tests")
|
||||||
(:file "pipeline-tests")
|
(:file "pipeline-tests")
|
||||||
|
(:file "peripheral-vision-tests")
|
||||||
(:file "boot-sequence-tests")
|
(:file "boot-sequence-tests")
|
||||||
(:file "object-store-tests")
|
(:file "object-store-tests")
|
||||||
(:file "immune-system-tests")
|
(:file "immune-system-tests")
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
:perform (test-op (o s)
|
:perform (test-op (o s)
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :oacp-suite :org-agent-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :oacp-suite :org-agent-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :pipeline-suite :org-agent-pipeline-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :pipeline-suite :org-agent-pipeline-tests))
|
||||||
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :vision-suite :org-agent-peripheral-vision-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :boot-suite :org-agent-boot-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :boot-suite :org-agent-boot-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :object-store-suite :org-agent-object-store-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :object-store-suite :org-agent-object-store-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :immune-suite :org-agent-immune-system-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :immune-suite :org-agent-immune-system-tests))
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
:components ((:module "tests"
|
:components ((:module "tests"
|
||||||
:components ((:file "oacp-tests")
|
:components ((:file "oacp-tests")
|
||||||
(:file "pipeline-tests")
|
(:file "pipeline-tests")
|
||||||
|
(:file "peripheral-vision-tests")
|
||||||
(:file "boot-sequence-tests")
|
(:file "boot-sequence-tests")
|
||||||
(:file "object-store-tests")
|
(:file "object-store-tests")
|
||||||
(:file "immune-system-tests")
|
(:file "immune-system-tests")
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
:perform (test-op (o s)
|
:perform (test-op (o s)
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :oacp-suite :org-agent-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :oacp-suite :org-agent-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :pipeline-suite :org-agent-pipeline-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :pipeline-suite :org-agent-pipeline-tests))
|
||||||
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :vision-suite :org-agent-peripheral-vision-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :boot-suite :org-agent-boot-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :boot-suite :org-agent-boot-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :object-store-suite :org-agent-object-store-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :object-store-suite :org-agent-object-store-tests))
|
||||||
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :immune-suite :org-agent-immune-system-tests))
|
(uiop:symbol-call :fiveam :run! (uiop:find-symbol* :immune-suite :org-agent-immune-system-tests))
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
(remove-if (lambda (obj) (equal (getf (org-object-attributes obj) :TODO-STATE) "DONE"))
|
(remove-if (lambda (obj) (equal (getf (org-object-attributes obj) :TODO-STATE) "DONE"))
|
||||||
(context-query-store :tag "project" :type :HEADLINE)))
|
(context-query-store :tag "project" :type :HEADLINE)))
|
||||||
|
|
||||||
(defun context-get-recent-completed-tasks () (context-query-store :todo-state "DONE" :type :HEADLINE))
|
(defun context-get-recent-completed-tasks ()
|
||||||
"Retrieves recently finished tasks from the store."
|
"Retrieves recently finished tasks from the store."
|
||||||
(defun context-list-all-skills ()
|
(context-query-store :todo-state "DONE" :type :HEADLINE))
|
||||||
|
|
||||||
|
(defun context-list-all-skills ()
|
||||||
"Provides a sorted overview of currently loaded system capabilities."
|
"Provides a sorted overview of currently loaded system capabilities."
|
||||||
(let ((results nil))
|
(let ((results nil))
|
||||||
(maphash (lambda (name skill)
|
(maphash (lambda (name skill)
|
||||||
@@ -45,15 +47,29 @@
|
|||||||
"Returns performance and execution data for a specific skill."
|
"Returns performance and execution data for a specific skill."
|
||||||
(bt:with-lock-held (*telemetry-lock*) (gethash (string-downcase skill-name) *skill-telemetry*)))
|
(bt:with-lock-held (*telemetry-lock*) (gethash (string-downcase skill-name) *skill-telemetry*)))
|
||||||
|
|
||||||
(defun context-filter-sparse-tree (ast predicate)
|
(defun context-render-to-org (obj &key (depth 1) (foveal-id nil))
|
||||||
"Prunes an AST to show only nodes matching a predicate and their ancestors."
|
"Recursively renders an org-object and its children to an Org string."
|
||||||
(if (listp ast)
|
(let* ((is-foveal (equal (org-object-id obj) foveal-id))
|
||||||
(let* ((contents (getf ast :contents))
|
(title (or (getf (org-object-attributes obj) :TITLE) "Untitled"))
|
||||||
(filtered-contents (remove-if #'null (mapcar (lambda (c) (context-filter-sparse-tree c predicate)) contents))))
|
(id (org-object-id obj))
|
||||||
(if (or (funcall predicate ast) (not (null filtered-contents)))
|
(content (org-object-content obj))
|
||||||
(let ((new-ast (copy-list ast))) (setf (getf new-ast :contents) filtered-contents) new-ast)
|
(children (org-object-children obj))
|
||||||
nil))
|
(stars (make-string depth :initial-element #\*))
|
||||||
nil))
|
(output (format nil "~a ~a~%:PROPERTIES:~%:ID: ~a~%:END:~%" stars title id)))
|
||||||
|
|
||||||
|
;; Only include content if this is the foveal focus
|
||||||
|
(when (and is-foveal content)
|
||||||
|
(setf output (concatenate 'string output content (string #\Newline))))
|
||||||
|
|
||||||
|
;; Recursively render children
|
||||||
|
(dolist (child-id children)
|
||||||
|
(let ((child-obj (lookup-object child-id)))
|
||||||
|
(when child-obj
|
||||||
|
(setf output (concatenate 'string output
|
||||||
|
(context-render-to-org child-obj
|
||||||
|
:depth (1+ depth)
|
||||||
|
:foveal-id foveal-id))))))
|
||||||
|
output))
|
||||||
|
|
||||||
(defun context-resolve-path (path-string)
|
(defun context-resolve-path (path-string)
|
||||||
"Expands environment variables within path strings (e.g. $HOME/...)."
|
"Expands environment variables within path strings (e.g. $HOME/...)."
|
||||||
@@ -66,16 +82,16 @@
|
|||||||
path-string))
|
path-string))
|
||||||
path-string))
|
path-string))
|
||||||
|
|
||||||
(defun context-assemble-global-awareness ()
|
(defun context-assemble-global-awareness (&optional signal)
|
||||||
"Produces a high-level skeletal outline of the current Object Store for the LLM."
|
"Produces a high-level skeletal outline of the current Object Store for the LLM."
|
||||||
(let ((projects (context-get-active-projects))
|
(let* ((payload (when signal (getf signal :payload)))
|
||||||
(output "GLOBAL MEMEX AWARENESS (Peripheral Vision):
|
(foveal-id (when payload (getf payload :target-id)))
|
||||||
|
(projects (context-get-active-projects))
|
||||||
|
(output "GLOBAL MEMEX AWARENESS (Peripheral Vision):
|
||||||
"))
|
"))
|
||||||
(if projects
|
(if projects
|
||||||
(dolist (project projects)
|
(dolist (project projects)
|
||||||
(setf output (concatenate 'string output
|
(setf output (concatenate 'string output
|
||||||
(format nil "- PROJECT: ~a (ID: ~a)~%"
|
(context-render-to-org project :foveal-id foveal-id))))
|
||||||
(getf (org-object-attributes project) :TITLE)
|
|
||||||
(org-object-id project)))))
|
|
||||||
(setf output (concatenate 'string output "No active projects found.~%")))
|
(setf output (concatenate 'string output "No active projects found.~%")))
|
||||||
output))
|
output))
|
||||||
|
|||||||
@@ -12,11 +12,15 @@
|
|||||||
(cdr (assoc :values (cdr (assoc :embedding json)))))
|
(cdr (assoc :values (cdr (assoc :embedding json)))))
|
||||||
(error (c) (kernel-log "EMBEDDING FAILURE: ~a" c) nil)))))
|
(error (c) (kernel-log "EMBEDDING FAILURE: ~a" c) nil)))))
|
||||||
|
|
||||||
(defun dot-product (v1 v2) (reduce #'+ (mapcar #'* v1 v2)))
|
(defun dot-product (v1 v2)
|
||||||
"Calculates the dot product of two numerical vectors."
|
"Calculates the dot product of two numerical vectors."
|
||||||
(defun magnitude (v) (sqrt (reduce #'+ (mapcar (lambda (x) (* x x)) v))))
|
(reduce #'+ (mapcar #'* v1 v2)))
|
||||||
|
|
||||||
|
(defun magnitude (v)
|
||||||
"Calculates the Euclidean magnitude of a numerical vector."
|
"Calculates the Euclidean magnitude of a numerical vector."
|
||||||
(defun cosine-similarity (v1 v2)
|
(sqrt (reduce #'+ (mapcar (lambda (x) (* x x)) v))))
|
||||||
|
|
||||||
|
(defun cosine-similarity (v1 v2)
|
||||||
"Calculates the semantic distance between two vectors."
|
"Calculates the semantic distance between two vectors."
|
||||||
(let ((m1 (magnitude v1)) (m2 (magnitude v2))) (if (or (zerop m1) (zerop m2)) 0 (/ (dot-product v1 v2) (* m1 m2)))))
|
(let ((m1 (magnitude v1)) (m2 (magnitude v2))) (if (or (zerop m1) (zerop m2)) 0 (/ (dot-product v1 v2) (* m1 m2)))))
|
||||||
|
|
||||||
|
|||||||
32
tests/peripheral-vision-tests.lisp
Normal file
32
tests/peripheral-vision-tests.lisp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
(defpackage :org-agent-peripheral-vision-tests
|
||||||
|
(:use :cl :fiveam :org-agent))
|
||||||
|
(in-package :org-agent-peripheral-vision-tests)
|
||||||
|
|
||||||
|
(def-suite vision-suite
|
||||||
|
:description "Verification of Foveal-Peripheral context model.")
|
||||||
|
(in-suite vision-suite)
|
||||||
|
|
||||||
|
(test test-foveal-rendering
|
||||||
|
"Verify that the foveal target is rendered with content, while siblings are skeletal."
|
||||||
|
(clrhash org-agent::*object-store*)
|
||||||
|
(let* ((ast '(:type :HEADLINE :properties (:ID "proj-root" :TITLE "Project" :TAGS "project")
|
||||||
|
:contents ((:type :HEADLINE :properties (:ID "node-foveal" :TITLE "Foveal Node")
|
||||||
|
:raw-content "FOVEAL CONTENT" :contents nil)
|
||||||
|
(:type :HEADLINE :properties (:ID "node-peripheral" :TITLE "Peripheral Node")
|
||||||
|
:raw-content "PERIPHERAL CONTENT" :contents nil)))))
|
||||||
|
(ingest-ast ast)
|
||||||
|
(let ((output (context-assemble-global-awareness (list :payload (list :target-id "node-foveal")))))
|
||||||
|
;; Foveal node should have its content
|
||||||
|
(is (search "FOVEAL CONTENT" output))
|
||||||
|
;; Peripheral node should be skeletal (only title/ID)
|
||||||
|
(is (search "* Peripheral Node" output))
|
||||||
|
(is (not (search "PERIPHERAL CONTENT" output))))))
|
||||||
|
|
||||||
|
(test test-awareness-budget
|
||||||
|
"Verify that context-assemble-global-awareness handles multiple projects."
|
||||||
|
(clrhash org-agent::*object-store*)
|
||||||
|
(ingest-ast '(:type :HEADLINE :properties (:ID "p1" :TITLE "Project 1" :TAGS "project") :contents nil))
|
||||||
|
(ingest-ast '(:type :HEADLINE :properties (:ID "p2" :TITLE "Project 2" :TAGS "project") :contents nil))
|
||||||
|
(let ((output (context-assemble-global-awareness)))
|
||||||
|
(is (search "Project 1" output))
|
||||||
|
(is (search "Project 2" output))))
|
||||||
Reference in New Issue
Block a user