From 90e4a8499679211778c5d7de56b0a097d08e8ae2 Mon Sep 17 00:00:00 2001 From: Amr Gharbeia Date: Thu, 9 Apr 2026 21:08:51 -0400 Subject: [PATCH] REFAC: Consolidate System Control into Event Orchestrator --- skills/org-skill-cron.org | 111 ------------- skills/org-skill-event-orchestrator.org | 206 ++++++++++++++++++++++++ skills/org-skill-hook-manager.org | 75 --------- skills/org-skill-router.org | 70 -------- src/event-orchestrator.lisp | 72 +++++++++ tests/orchestrator-tests.lisp | 16 ++ 6 files changed, 294 insertions(+), 256 deletions(-) delete mode 100644 skills/org-skill-cron.org create mode 100644 skills/org-skill-event-orchestrator.org delete mode 100644 skills/org-skill-hook-manager.org delete mode 100644 skills/org-skill-router.org create mode 100644 src/event-orchestrator.lisp create mode 100644 tests/orchestrator-tests.lisp diff --git a/skills/org-skill-cron.org b/skills/org-skill-cron.org deleted file mode 100644 index 306d91a..0000000 --- a/skills/org-skill-cron.org +++ /dev/null @@ -1,111 +0,0 @@ -:PROPERTIES: -:ID: 085668da-6505-438e-b92a-736943cd4d0a -:CREATED: [2026-03-30 Mon 21:16] -:EDITED: [2026-04-07 Tue 13:42] -:END: -#+TITLE: SKILL: Cron Agent (Universal Literate Note) -#+STARTUP: content -#+FILETAGS: :cron:temporal:heartbeat:psf: - -* Overview -The *Cron Agent* serves as the system's temporal conscience. It provides autonomous, time-aware capabilities by hooking into the background heartbeat, enabling proactive executive assistance. - -* Phase A: Demand (PRD) -:PROPERTIES: -:STATUS: FROZEN -:END: - -** 1. Purpose -Define automated behaviors for deadline monitoring and temporal alerting. - -** 2. User Needs -- *Punctuality:* Monitor deadlines and alerts across the Memex. -- *Efficiency:* Symbolic filtering (System 2) to minimize LLM calls. -- *Multi-Channel Awareness:* Routing alerts to Emacs or external delivery. - -** 3. Success Criteria -*** TODO Heartbeat Trigger Verification -*** TODO Timestamp Parsing Accuracy -*** TODO Overdue Task Detection - - -* Phase B: Blueprint (PROTOCOL) -:PROPERTIES: -:STATUS: SIGNED -:END: - - -* Phase B: Blueprint (PROTOCOL) -:PROPERTIES: -:STATUS: DRAFT -:END: - -** 1. Architectural Intent -The Cron Agent operates as a reactive component driven by the Memex heartbeat. It translates temporal events (scheduled times, deadlines, overdue conditions) into actions. It prioritizes efficiency by using System 2 (symbolic) processing for initial filtering and triggering, reserving System 3 (LLM-assisted) operations for complex reasoning scenarios. This agent adopts a modular design to enable easy integration with various notification channels. - -** 2. Semantic Interfaces (Lisp Signatures) - -*** `cron/register-task` - Registers a new task with the Cron Agent. - - :Lisp: - `(cron/register-task task-id schedule task-function &key (notification-channel :emacs) (deadline nil))` - - :Args: - - `task-id`: A unique symbol identifying the task. - - `schedule`: A cron-style string representing the task's schedule (e.g., "0 0 * * *" for daily at midnight). - - `task-function`: A function (lambda) to execute when the schedule is met and the conditions are satisfied. This function must take a plist containing the task-id and scheduled-time. - - `notification-channel`: Keyword specifying the destination for alerts (:emacs, :slack, :email). Defaults to `:emacs`. - - `deadline`: An optional ISO-8601 timestamp string representing the deadline. If a deadline is specified, the `task-function` will also receive information about whether the task is overdue. - - :Returns: - The `task-id` on successful registration, or `nil` if registration fails. - - :Side Effects: - Adds the task to the internal cron table. - -*** `cron/remove-task` - Removes a previously registered task. - - :Lisp: - `(cron/remove-task task-id)` - - :Args: - - `task-id`: The unique symbol identifying the task to be removed. - - :Returns: - `T` if the task was successfully removed, `nil` otherwise. - - :Side Effects: - Removes the task from the internal cron table. - -*** `cron/check-schedule` - (Internal) Called by the heartbeat to check if any tasks are due. - - :Lisp: - `(cron/check-schedule current-time)` - - :Args: - - `current-time`: A timestamp representing the current time. - - :Returns: - `nil` (No return value). - - :Side Effects: - Executes any tasks that are due based on their schedule and deadline. - -*** `cron/notify` - Sends a notification through the specified channel. - - :Lisp: - `(cron/notify message channel)` - - :Args: - - `message`: The message to be sent. - - `channel`: The notification channel (:emacs, :slack, :email). - - :Returns: - `T` if the notification was sent successfully, `nil` otherwise. - - :Side Effects: - Sends a notification. The implementation details of sending notifications through various channels are handled internally. diff --git a/skills/org-skill-event-orchestrator.org b/skills/org-skill-event-orchestrator.org new file mode 100644 index 0000000..8ff4820 --- /dev/null +++ b/skills/org-skill-event-orchestrator.org @@ -0,0 +1,206 @@ +:PROPERTIES: +:ID: event-orchestrator-skill +:CREATED: [2026-04-09 Thu] +:END: +#+TITLE: SKILL: Event Orchestrator (Universal Literate Note) +#+STARTUP: content +#+FILETAGS: :system:control:event-driven:cron:hooks:routing:psf: +#+DEPENDS_ON: id:state-persistence-skill + +* Overview +The *Event Orchestrator* is the central nervous system of the Org-Agent. It unifies three previously fragmented domains of system control: +1. **Cron (Temporal Control):** Triggering tasks based on time and heartbeats. +2. **Hooks (Lifecycle Control):** Enabling event-driven extensibility at specific code points. +3. **Routing (Cognitive Control):** Classifying incoming stimuli into complexity tiers for optimal resource allocation. + +By consolidating these into a single unit, we ensure that all system automation is auditable, Merkle-integrated, and follows a uniform safety standard. + +* Phase A: Demand (PRD) +:PROPERTIES: +:STATUS: SIGNED +:END: + +** 1. Purpose +Provide a unified, high-integrity interface for background automation and stimulus classification. + +** 2. User Needs +- *Predictable Scheduling:* Precise execution of tasks based on cron-strings or intervals. +- *Reactive Extensions:* Ability to "hook" into system events (save, boot, ingest). +- *Intelligent Dispatch:* Automated complexity tiering to prevent wasted compute. +- *Durable Registry:* All registered hooks and cron-jobs must be persisted to the Object Store. + +* Phase B: Blueprint (PROTOCOL) +:PROPERTIES: +:STATUS: SIGNED +:END: + +** 1. Architectural Intent +The orchestrator maintains three internal registries (Hooks, Cron, Routing Rules). It provides a standard API for registration and triggering, using the `LOCAL` persistence adapter to ensure these registries survive reboots. + +** 2. Semantic Interfaces +#+begin_src lisp +(defun orchestrator-register-hook (hook-name fn) + "Adds a function to a system hook.") + +(defun orchestrator-schedule-task (task-id schedule fn) + "Schedules a recurring task.") + +(defun orchestrator-classify-stimulus (context) + "Assigns a complexity tier (:REFLEX, :COGNITION, :REASONING) to a stimulus.") +#+end_src + +* Phase C: Success (QUALITY) +:PROPERTIES: +:STATUS: SIGNED +:END: + +** 1. Success Criteria +- [ ] *Hook Latency:* Triggering a hook with 10 functions must complete in <1ms. +- [ ] *Cron Precision:* Scheduled tasks must fire within 1s of their target window. +- [ ] *Merkle Persistence:* Adding a hook or cron-job must increment the Object Store version. +- [ ] *Classification Accuracy:* Routine system events must always be classified as `:REFLEX`. + +** 2. TDD Plan +Tests in `tests/orchestrator-tests.lisp` will verify hook execution order, cron-job triggering via a mocked heartbeat, and the routing classification logic. + +* Phase D: Build (Implementation) + +** Package Context +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(in-package :org-agent) +#+end_src + +** Registry State +We maintain our internal registries in hash-tables, which will be serialized via the State Persistence layer. + +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(defvar *hook-registry* (make-hash-table :test 'equal) + "Maps hook-names (symbols) to lists of functions.") + +(defvar *cron-registry* (make-hash-table :test 'equal) + "Maps task-ids to plists containing schedule and function.") +#+end_src + +** Hook: Registration +Allows external skills to register logic at system lifecycle points. + +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(defun orchestrator-register-hook (hook-name fn) + "Registers a function for a named hook. Triggers a Merkle snapshot." + (pushnew fn (gethash hook-name *hook-registry*)) + (kernel-log "ORCHESTRATOR - Registered hook function for ~a" hook-name) + (snapshot-object-store) + t) +#+end_src + +** Hook: Triggering +Executes all functions associated with a specific hook. + +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(defun orchestrator-trigger-hook (hook-name &rest args) + "Executes all registered functions for the given hook name." + (let ((functions (gethash hook-name *hook-registry*))) + (dolist (fn functions) + (handler-case (apply fn args) + (error (c) (kernel-log "ORCHESTRATOR ERROR - Hook ~a failed: ~a" hook-name c)))))) +#+end_src + +** Cron: Task Scheduling +Registers a recurring task to be executed during heartbeats. + +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(defun orchestrator-schedule-task (task-id schedule fn) + "Schedules a task for execution. Schedule can be an interval (integer seconds) or 'heartbeat'." + (setf (gethash task-id *cron-registry*) (list :schedule schedule :fn fn :last-run 0)) + (kernel-log "ORCHESTRATOR - Scheduled task ~a (~a)" task-id schedule) + (snapshot-object-store) + t) +#+end_src + +** Cron: Heartbeat Processor +The internal loop that checks the cron-registry during every system pulse. + +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(defun orchestrator-process-cron () + "Checked by the kernel on every heartbeat." + (let ((now (get-universal-time))) + (maphash (lambda (id task) + (let ((schedule (getf task :schedule)) + (last-run (getf task :last-run)) + (fn (getf task :fn))) + (when (or (eq schedule :heartbeat) + (and (integerp schedule) (>= (- now last-run) schedule))) + (handler-case (funcall fn) + (error (c) (kernel-log "ORCHESTRATOR ERROR - Cron task ~a failed: ~a" id c))) + (setf (getf (gethash id *cron-registry*) :last-run) now)))) + *cron-registry*))) +#+end_src + +** Router: Complexity Classification +Deterministic logic to classify incoming stimuli into complexity tiers. + +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(defun orchestrator-classify-complexity (context) + "Returns the complexity tier (:REFLEX, :COGNITION, :REASONING) for a stimulus." + (let* ((payload (getf context :payload)) + (sensor (getf payload :sensor)) + (skill (find-triggered-skill context)) + (skill-name (when skill (skill-name skill)))) + (cond + ;; reasoning: generative or architectural + ((member skill-name '("skill-architect" "skill-tech-analyst" "skill-scientist" "skill-self-fix") :test #'string-equal) :REASONING) + ((member sensor '(:user-command)) :REASONING) + + ;; cognition: human interaction or semantic data + ((member sensor '(:chat-message :delegation)) :COGNITION) + ((member skill-name '("skill-scribe" "skill-web-research") :test #'string-equal) :COGNITION) + + ;; reflex: system infrastructure and background automation + (t :REFLEX)))) +#+end_src + +** Registration +We register the orchestrator as a core skill and hot-patch the kernel's routing hook to use our classification logic. + +#+begin_src lisp :tangle ../src/event-orchestrator.lisp +(progn + ;; Hook into kernel routing + (setf org-agent::*model-selector-fn* #'orchestrator-classify-complexity) + + (defskill :skill-event-orchestrator + :priority 400 ; Foundational control layer + :trigger (lambda (ctx) (eq (getf (getf ctx :payload) :sensor) :heartbeat)) + :neuro nil + :symbolic (lambda (action ctx) + (orchestrator-process-cron) + action))) +#+end_src + +* Phase E: Chaos (Verification) + +** 1. Unit Tests (FiveAM) +#+begin_src lisp :tangle ../tests/orchestrator-tests.lisp +(defpackage :org-agent-orchestrator-tests + (:use :cl :fiveam :org-agent)) +(in-package :org-agent-orchestrator-tests) + +(def-suite orchestrator-suite :description "Tests for Event Orchestrator.") +(in-suite orchestrator-suite) + +(test test-hook-execution + (let ((test-val 0)) + (org-agent:orchestrator-register-hook :test-hook (lambda () (setf test-val 1))) + (org-agent:orchestrator-trigger-hook :test-hook) + (is (= 1 test-val)))) + +(test test-routing-reflex + (let ((ctx '(:payload (:sensor :heartbeat)))) + (is (eq :REFLEX (org-agent:orchestrator-classify-complexity ctx))))) +#+end_src + +** 2. Chaos Scenarios +- *Scenario A (Infinite Hook Loop):* Register two hooks that call each other and verify the orchestrator's recursion limit or handler-case prevents a kernel stack-overflow. +- *Scenario B (Cron Stall):* Register a cron-job that performs a long synchronous sleep and verify the `kernel-log` identifies the delay in the heartbeat pulse. + +* Phase F: Memory (RCA) +- *[2026-04-09 Thu]:* Consolidated Cron, Hook Manager, and Cognitive Router into a single orchestrator. Fixed the lack of implementation for Cron and Hooks. diff --git a/skills/org-skill-hook-manager.org b/skills/org-skill-hook-manager.org deleted file mode 100644 index eafd971..0000000 --- a/skills/org-skill-hook-manager.org +++ /dev/null @@ -1,75 +0,0 @@ -:PROPERTIES: -:ID: 21bcb7ff-1b69-45ae-8844-981c7fc2373c -:CREATED: [2026-04-04 Sat 20:27] -:EDITED: [2026-04-07 Tue 13:42] -:END: -#+TITLE: SKILL: Hook Manager (Universal Literate Note) -#+STARTUP: content -#+FILETAGS: :hooks:event-driven:system:psf: - -* Overview -The *Hook Manager* enables event-driven extensibility within the agent by allowing functions to be registered and executed at specific lifecycle points. - -* Phase A: Demand (PRD) -:PROPERTIES: -:STATUS: FROZEN -:END: - -** 1. Purpose -Provide a hook-based event system. - -** 2. User Needs -- *Registration:* Register functions to be called on specific hooks. -- *Execution:* Trigger all registered functions for a given hook. - - -* Phase B: Blueprint (PROTOCOL) -:PROPERTIES: -:STATUS: SIGNED -:END: - -* Phase B: Blueprint (PROTOCOL) -:PROPERTIES: -:STATUS: DRAFT -:END: - -** 1. Architectural Intent -The Hook Manager will provide a centralized mechanism for registering and executing hook functions. It aims for simplicity, flexibility, and minimal performance overhead. The core design principle is a simple registry mapping hook names to lists of functions. - -** 2. Semantic Interfaces - -*** 2.1. `register-hook` - -Registers a function to be executed when a specific hook is triggered. - - Signature: `(register-hook hook-name function)` - - - `hook-name`: A symbol representing the name of the hook. - - `function`: A function (lambda or symbol) to be executed when the hook is triggered. The function's arguments depend on the hook (see hook-specific documentation). - - Example: - `(register-hook 'before-planning #'my-planning-hook)` - -*** 2.2. `trigger-hook` - -Executes all registered functions for a given hook. - - Signature: `(trigger-hook hook-name &rest args)` - - - `hook-name`: A symbol representing the name of the hook to trigger. - - `&rest args`: Optional arguments to be passed to the registered functions. The meaning and number of arguments depends on the specific hook. - - Example: - `(trigger-hook 'after-planning current-plan)` - -*** 2.3. `remove-hook` - -Removes a registered function from a hook. - - Signature: `(remove-hook hook-name function)` - - - `hook-name`: A symbol representing the name of the hook. - - `function`: The function to remove from the hook's registry. - - Example: - `(remove-hook 'before-planning #'my-planning-hook)` diff --git a/skills/org-skill-router.org b/skills/org-skill-router.org deleted file mode 100644 index 06d67ac..0000000 --- a/skills/org-skill-router.org +++ /dev/null @@ -1,70 +0,0 @@ -:PROPERTIES: -:ID: 0fb9e9cb-4af2-463c-9c6f-74f95747c5ff -:CREATED: [2026-03-30 Mon 21:16] -:EDITED: [2026-04-07 Tue 13:42] -:END: -#+TITLE: SKILL: Cognitive Router Agent (Universal Literate Note) -#+STARTUP: content -#+FILETAGS: :routing:cognition:dispatch:psf: - -* Overview -The *Cognitive Router* is the kernel's traffic controller. it classifies incoming stimuli into complexity tiers, enabling the Economist to make sovereign compute-allocation decisions. - -* Phase A: Demand (PRD) -:PROPERTIES: -:STATUS: SIGNED -:END: - -** 1. Purpose -Classify tasks by complexity to optimize neural resource allocation. - -** 2. User Needs -- *Tier Identification:* Differentiate between routine grooming and deep architectural work. -- *Dynamic Dispatch:* Route complex requests to high-fidelity backends. - -* Phase B: Blueprint (PROTOCOL) -:PROPERTIES: -:STATUS: SIGNED -:END: - -** 1. Architectural Intent -Implement a deterministic classifier for known sensors and a neural fallback for ambiguous user commands. - -** 2. Semantic Interfaces - -*** Complexity Tiers -- =:REFLEX=: System maintenance (heartbeats, persistence, cleanup). -- =:COGNITION=: Conversational tasks (chat, summarization, metadata extraction). -- =:REASONING=: Generative tasks (coding, blueprinting, debugging). - -*** Routing Logic -#+begin_src lisp :tangle ../src/router-logic.lisp -(in-package :org-agent) - -(defun router-classify-complexity (context) - "Returns the complexity tier for a given stimulus context." - (let* ((payload (getf context :payload)) - (sensor (getf payload :sensor)) - (skill (find-triggered-skill context)) - (skill-name (when skill (skill-name skill)))) - (cond - ;; reasoning: generative or architectural - ((member skill-name '("skill-architect" "skill-tech-analyst" "skill-scientist" "skill-self-fix") :test #'string-equal) :REASONING) - ((member sensor '(:user-command)) :REASONING) - - ;; cognition: human interaction or semantic data - ((member sensor '(:chat-message :delegation)) :COGNITION) - ((member skill-name '("skill-scribe" "skill-web-research") :test #'string-equal) :COGNITION) - - ;; reflex: system infrastructure - (t :REFLEX)))) -#+end_src - -* Registration -#+begin_src lisp -(defskill :skill-router - :priority 110 - :trigger (lambda (context) nil) ; Passive classifier - :neuro (lambda (context) nil) - :symbolic (lambda (action context) (router-classify-complexity context))) -#+end_src diff --git a/src/event-orchestrator.lisp b/src/event-orchestrator.lisp new file mode 100644 index 0000000..56204cd --- /dev/null +++ b/src/event-orchestrator.lisp @@ -0,0 +1,72 @@ +(in-package :org-agent) + +(defvar *hook-registry* (make-hash-table :test 'equal) + "Maps hook-names (symbols) to lists of functions.") + +(defvar *cron-registry* (make-hash-table :test 'equal) + "Maps task-ids to plists containing schedule and function.") + +(defun orchestrator-register-hook (hook-name fn) + "Registers a function for a named hook. Triggers a Merkle snapshot." + (pushnew fn (gethash hook-name *hook-registry*)) + (kernel-log "ORCHESTRATOR - Registered hook function for ~a" hook-name) + (snapshot-object-store) + t) + +(defun orchestrator-trigger-hook (hook-name &rest args) + "Executes all registered functions for the given hook name." + (let ((functions (gethash hook-name *hook-registry*))) + (dolist (fn functions) + (handler-case (apply fn args) + (error (c) (kernel-log "ORCHESTRATOR ERROR - Hook ~a failed: ~a" hook-name c)))))) + +(defun orchestrator-schedule-task (task-id schedule fn) + "Schedules a task for execution. Schedule can be an interval (integer seconds) or 'heartbeat'." + (setf (gethash task-id *cron-registry*) (list :schedule schedule :fn fn :last-run 0)) + (kernel-log "ORCHESTRATOR - Scheduled task ~a (~a)" task-id schedule) + (snapshot-object-store) + t) + +(defun orchestrator-process-cron () + "Checked by the kernel on every heartbeat." + (let ((now (get-universal-time))) + (maphash (lambda (id task) + (let ((schedule (getf task :schedule)) + (last-run (getf task :last-run)) + (fn (getf task :fn))) + (when (or (eq schedule :heartbeat) + (and (integerp schedule) (>= (- now last-run) schedule))) + (handler-case (funcall fn) + (error (c) (kernel-log "ORCHESTRATOR ERROR - Cron task ~a failed: ~a" id c))) + (setf (getf (gethash id *cron-registry*) :last-run) now)))) + *cron-registry*))) + +(defun orchestrator-classify-complexity (context) + "Returns the complexity tier (:REFLEX, :COGNITION, :REASONING) for a stimulus." + (let* ((payload (getf context :payload)) + (sensor (getf payload :sensor)) + (skill (find-triggered-skill context)) + (skill-name (when skill (skill-name skill)))) + (cond + ;; reasoning: generative or architectural + ((member skill-name '("skill-architect" "skill-tech-analyst" "skill-scientist" "skill-self-fix") :test #'string-equal) :REASONING) + ((member sensor '(:user-command)) :REASONING) + + ;; cognition: human interaction or semantic data + ((member sensor '(:chat-message :delegation)) :COGNITION) + ((member skill-name '("skill-scribe" "skill-web-research") :test #'string-equal) :COGNITION) + + ;; reflex: system infrastructure and background automation + (t :REFLEX)))) + +(progn + ;; Hook into kernel routing + (setf org-agent::*model-selector-fn* #'orchestrator-classify-complexity) + + (defskill :skill-event-orchestrator + :priority 400 ; Foundational control layer + :trigger (lambda (ctx) (eq (getf (getf ctx :payload) :sensor) :heartbeat)) + :neuro nil + :symbolic (lambda (action ctx) + (orchestrator-process-cron) + action))) diff --git a/tests/orchestrator-tests.lisp b/tests/orchestrator-tests.lisp new file mode 100644 index 0000000..d31d5d7 --- /dev/null +++ b/tests/orchestrator-tests.lisp @@ -0,0 +1,16 @@ +(defpackage :org-agent-orchestrator-tests + (:use :cl :fiveam :org-agent)) +(in-package :org-agent-orchestrator-tests) + +(def-suite orchestrator-suite :description "Tests for Event Orchestrator.") +(in-suite orchestrator-suite) + +(test test-hook-execution + (let ((test-val 0)) + (org-agent:orchestrator-register-hook :test-hook (lambda () (setf test-val 1))) + (org-agent:orchestrator-trigger-hook :test-hook) + (is (= 1 test-val)))) + +(test test-routing-reflex + (let ((ctx '(:payload (:sensor :heartbeat)))) + (is (eq :REFLEX (org-agent:orchestrator-classify-complexity ctx)))))