(defvar *cron-registry* nil) (defun cron-register (name schedule-fn action-fn) "Register a new cron task." (push (list :name name :schedule schedule-fn :action action-fn :last-run 0) *cron-registry*)) (defun cron-trigger-loop () "Iterate through registered tasks and trigger those whose schedule matches." (dolist (task *cron-registry*) (let ((name (getf task :name)) (schedule (getf task :schedule)) (action (getf task :action))) (when (funcall schedule) (kernel-log "CRON - Triggering task: ~a" name) (funcall action) (setf (getf task :last-run) (get-universal-time)))))) (defun trigger-skill-cron (context) (let ((type (getf context :type)) (payload (getf context :payload))) (when (and (eq type :EVENT) (eq (getf payload :sensor) :heartbeat)) (cron-trigger-loop) (trigger-nightly-grooming) t))) (defun parse-org-timestamp (ts-str) (let ((match (nth-value 1 (cl-ppcre:scan-to-strings "<(\\d{4})-(\\d{2})-(\\d{2}).*>" ts-str)))) (if match (encode-universal-time 0 0 0 (parse-integer (aref match 2)) (parse-integer (aref match 1)) (parse-integer (aref match 0))) nil))) (defun trigger-nightly-grooming () "Checks if the current time is within the nightly grooming window (e.g., 3:00 AM - 4:00 AM)." (let* ((now (local-time:now)) (hour (local-time:timestamp-hour now))) (when (= hour 3) (kernel-log "CRON - Initiating Nightly Grooming Cycle...") (org-agent:inject-stimulus `(:type :EVENT :payload (:sensor :grooming-cycle)))))) (defun context-get-upcoming-deadlines (&optional (days 3)) (let* ((now (get-universal-time)) (future-limit (+ now (* days 24 60 60))) (all-headlines (org-agent:list-objects-by-type :HEADLINE)) (upcoming nil)) (dolist (obj all-headlines) (let* ((attrs (org-agent:org-object-attributes obj)) (deadline-str (getf attrs :DEADLINE)) (deadline-time (when deadline-str (parse-org-timestamp deadline-str)))) (when (and deadline-time (< deadline-time future-limit) (> deadline-time (- now 86400))) (push (list :title (getf attrs :TITLE) :deadline deadline-str) upcoming)))) upcoming)) (defun context-get-stalled-waiting-items (&optional (days 3)) (let* ((now (get-universal-time)) (past-limit (- now (* days 24 60 60))) (all-headlines (org-agent:list-objects-by-type :HEADLINE)) (stalled nil)) (dolist (obj all-headlines) (let* ((attrs (org-agent:org-object-attributes obj)) (state (getf attrs :TODO-STATE)) (last-sync (org-agent:org-object-last-sync obj))) (when (and (equal state "WAITING") (< last-sync past-limit)) (push (list :title (getf attrs :TITLE)) stalled)))) stalled)) (defun neuro-skill-cron (context) (let* ((upcoming (context-get-upcoming-deadlines 3)) (stalled (context-get-stalled-waiting-items 3)) (now-str (local-time:format-timestring nil (local-time:now)))) (format nil " CURRENT TIME: ~a UPCOMING DEADLINES (Next 3 Days): ~{~a: ~a~%~} STALLED WAITING ITEMS (> 3 days old): ~{~a~%~} " now-str (loop for item in upcoming append (list (getf item :deadline) (getf item :title))) (loop for item in stalled collect (getf item :title)))))