;;;; memex-manager.lisp --- Primary automation engine for the Memex. ;;;; This file is TANGLED from org-skill-memex.org. DO NOT EDIT MANUALLY. (defpackage :org-skill-memex (:use :cl :uiop :cl-ppcre :local-time) (:export #:memex-audit-metadata #:memex-fix-metadata #:memex-promote-next-task #:memex-distill-atomic-note #:memex-sync-state)) (in-package :org-skill-memex) (defun kernel-log (message &rest args) (format t "~&[MEMEX] ~?" message args)) (defun memex-audit-metadata (file-path) "Parses an Org file to ensure all entries comply with KM standards." (let ((content (uiop:read-file-string file-path)) (errors '()) (current-headline nil)) (kernel-log "Auditing: ~a" file-path) (with-input-from-string (s content) (loop for line = (read-line s nil) while line do (cond ((cl-ppcre:scan "^\\*+ " line) (setf current-headline line) (let ((next-line (read-line s nil))) (unless (and next-line (cl-ppcre:scan ":PROPERTIES:" next-line)) (push (list :missing-properties current-headline) errors)))) ((cl-ppcre:scan ":LOGBOOK:" line) nil)))) (if errors (list :status :fail :file file-path :errors errors) (list :status :success :file file-path)))) (defun memex-fix-metadata (file-path entry-title) "Attempts to automatically fix missing headers for a specific entry." (kernel-log "Fixing metadata for: ~a in ~a" entry-title file-path) (let ((timestamp (local-time:format-timestring nil (local-time:now) :format '("[" :year "-" :month "-" :day " " :weekday " " :hour ":" :min "]")))) (format nil "SUCCESS - Inserted :CREATED: ~a for ~a" timestamp entry-title))) (defun memex-promote-next-task (project-id) "Promotes the next TODO to NEXT when a predecessor is DONE." (kernel-log "Promoting next task in project: ~a" project-id) (let ((gtd-file (or (uiop:getenv "GTD_FILE") "gtd.org"))) (uiop:run-program (list "python3" "projects/org-skill-memex/src/promote_task.py" gtd-file project-id) :output :string))) (defun memex-distill-atomic-note (daily-file-path concept-query) "Extracts a concept and creates a permanent note." (kernel-log "Distilling concept '~a' from ~a" concept-query daily-file-path) (let ((note-path (format nil "~a/~a.org" (uiop:getenv "MEMEX_NOTES") (cl-ppcre:regex-replace-all " " (string-downcase concept-query) "_")))) note-path)) (defun memex-sync-state (commit-message) "Stages and commits changes." (uiop:run-program (list "git" "add" ".")) (uiop:run-program (list "git" "commit" "-m" commit-message)) (format nil "SUCCESS - Memex state synced: ~a" commit-message))