From 5d93f201bed3a47240d3346281e49b527c1523c6 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Sun, 3 May 2026 16:07:20 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20memory=20scope=20segmentation=20?= =?UTF-8?q?=E2=80=94=20wire=20context=20scope=20into=20perceive=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds *scope-resolver* hook in core-loop-perceive that the context-manager skill sets at load time. The perceive gate now passes the active scope to ingest-ast, tagging all ingested objects with the current context scope. Implementation: - core-loop-perceive: *scope-resolver* defvar (default nil → :memex), two ingest-ast calls now pass (if *scope-resolver* (funcall it) :memex) - core-defpackage: export *scope-resolver* and context-query - system-context-manager: auto-init sets *scope-resolver* to #'current-scope This completes the Memory Scope Segmentation feature: all three scopes (:memex, :session, :project) are supported, scope-aware retrieval (context-query :scope / context-scoped-query) was already implemented, and ingested objects now correctly carry the active scope. --- lisp/core-defpackage.lisp | 24 +++++++++++++----------- lisp/core-loop-perceive.lisp | 7 +++++-- lisp/system-context-manager.lisp | 3 +++ org/core-defpackage.org | 24 +++++++++++++----------- org/core-loop-perceive.org | 17 +++++++++++++++-- org/system-context-manager.org | 10 ++++++++++ 6 files changed, 59 insertions(+), 26 deletions(-) diff --git a/lisp/core-defpackage.lisp b/lisp/core-defpackage.lisp index 0631e8a..0333ca4 100644 --- a/lisp/core-defpackage.lisp +++ b/lisp/core-defpackage.lisp @@ -51,11 +51,12 @@ #: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 + #:context-get-system-logs + #:context-resolve-path + #:context-get-skill-telemetry + #:telemetry-track + #:context-assemble-global-awareness + #:context-query #:process-signal #:loop-process #:perceive-gate @@ -75,12 +76,13 @@ #: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-initialize-all + #:load-skill-with-timeout + #:topological-sort-skills + #:validate-lisp-syntax + #:defskill + #:*skill-registry* + #:*scope-resolver* #:skill #:skill-name #:skill-priority diff --git a/lisp/core-loop-perceive.lisp b/lisp/core-loop-perceive.lisp index 0bd1a59..b3d2a6d 100644 --- a/lisp/core-loop-perceive.lisp +++ b/lisp/core-loop-perceive.lisp @@ -2,6 +2,9 @@ (defvar *loop-interrupt* nil) +(defvar *scope-resolver* nil + "If set, function returning current scope keyword. Used by perceive gate.") + (defvar *loop-async-sensors* '(:chat-message :delegation :user-command) "Sensors that are processed in dedicated threads.") @@ -79,13 +82,13 @@ FN receives (signal) and returns T if consumed, nil to continue." (let ((ast (getf payload :ast))) (when ast (snapshot-memory) - (ingest-ast ast)))) + (ingest-ast ast :scope (if *scope-resolver* (funcall *scope-resolver*) :memex))))) (:point-update (let ((element (getf payload :element))) (when element (snapshot-memory) (setf *loop-focus-id* (getf element :id)) - (ingest-ast element)))) + (ingest-ast element :scope (if *scope-resolver* (funcall *scope-resolver*) :memex))))) (:interrupt (setf *loop-interrupt* t)) ;; HITL: re-injected approved action from dispatcher-approvals-process diff --git a/lisp/system-context-manager.lisp b/lisp/system-context-manager.lisp index 32dd5d9..a5f4f75 100644 --- a/lisp/system-context-manager.lisp +++ b/lisp/system-context-manager.lisp @@ -116,3 +116,6 @@ until stack is empty or :memex context is reached." (when (> (context-stack-depth) 0) nil)) nil)) + +(when (boundp '*scope-resolver*) + (setf *scope-resolver* #'current-scope)) diff --git a/org/core-defpackage.org b/org/core-defpackage.org index 092fa0b..45b4f61 100644 --- a/org/core-defpackage.org +++ b/org/core-defpackage.org @@ -76,11 +76,12 @@ The package definition. All public symbols are exported here. #: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 + #:context-get-system-logs + #:context-resolve-path + #:context-get-skill-telemetry + #:telemetry-track + #:context-assemble-global-awareness + #:context-query #:process-signal #:loop-process #:perceive-gate @@ -100,12 +101,13 @@ The package definition. All public symbols are exported here. #: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-initialize-all + #:load-skill-with-timeout + #:topological-sort-skills + #:validate-lisp-syntax + #:defskill + #:*skill-registry* + #:*scope-resolver* #:skill #:skill-name #:skill-priority diff --git a/org/core-loop-perceive.org b/org/core-loop-perceive.org index 6015194..3246218 100644 --- a/org/core-loop-perceive.org +++ b/org/core-loop-perceive.org @@ -43,6 +43,19 @@ A global interrupt flag that can be set by any signal. When set, the metabolic l (defvar *loop-interrupt* nil) #+end_src +** Scope Resolver + +A hook for the context-manager skill to register its ~current-scope~ +function. When set, the perceive gate passes the current context scope +to ~ingest-ast~ so ingested objects are tagged and queryable by scope. +Defaults to ~nil~ meaning all objects are ingested as ~:memex~. + +;; REPL-VERIFIED: 2026-05-03T14:00:00 +#+begin_src lisp +(defvar *scope-resolver* nil + "If set, function returning current scope keyword. Used by perceive gate.") +#+end_src + ** Sensor Configuration ~*loop-async-sensors*~ lists the sensor types that should be processed in their own threads. Currently, ~:chat-message~, ~:delegation~, and ~:user-command~ are async because they don't block the main reasoning loop — the agent can process a Telegram message while waiting for the user's next input. @@ -186,13 +199,13 @@ The main perceive pipeline stage. (let ((ast (getf payload :ast))) (when ast (snapshot-memory) - (ingest-ast ast)))) + (ingest-ast ast :scope (if *scope-resolver* (funcall *scope-resolver*) :memex))))) (:point-update (let ((element (getf payload :element))) (when element (snapshot-memory) (setf *loop-focus-id* (getf element :id)) - (ingest-ast element)))) + (ingest-ast element :scope (if *scope-resolver* (funcall *scope-resolver*) :memex))))) (:interrupt (setf *loop-interrupt* t)) ;; HITL: re-injected approved action from dispatcher-approvals-process diff --git a/org/system-context-manager.org b/org/system-context-manager.org index e1fa2f9..1565481 100644 --- a/org/system-context-manager.org +++ b/org/system-context-manager.org @@ -222,4 +222,14 @@ until stack is empty or :memex context is reached." (when (> (context-stack-depth) 0) nil)) nil)) +#+end_src + +** Auto-Init: Wire Scope Resolver + +Registers ~current-scope~ into the core ~*scope-resolver*~ hook so the +perceive gate tags ingested objects with the active context scope. + +#+begin_src lisp +(when (boundp '*scope-resolver*) + (setf *scope-resolver* #'current-scope)) #+end_src \ No newline at end of file