feat(core): Skills consolidation and v0.2.0 TUI integration
- NEW: org-skill-utils-lisp (consolidated from org-skill-lisp-utils) * 3-phase validation: structural, syntactic, semantic * Sandboxed eval, AST extraction/injection/wrapping * Format, list-definitions utilities - NEW: org-skill-utils-org (consolidated from org-skill-emacs-edit) * Read/update/delete org headlines * Property management, TODO state handling * ID-link and internal link support - DELETE: org-skill-lisp-utils (merged into utils-lisp) - DELETE: org-skill-emacs-edit (merged into utils-org) - RENAME: run-all-tests.lisp -> run-tests.lisp - HARDEN: Skill loader with improved lisp keyword handling - FIX: Package jailing issues with def-cognitive-tool macro conflicts - ADD: Setup wizard (opencortex setup) and doctor (opencortex doctor) - ADD: TUI client with Croatoan for native terminal rendering - REMOVE: Dynamic loading from opencortex.asd (use :force t instead) - CLEANUP: Test file consolidation (removed duplicate test suites) Co-authored-by: Agent <agent@memex>
This commit is contained in:
94
skills/org-skill-utils-org.lisp
Normal file
94
skills/org-skill-utils-org.lisp
Normal file
@@ -0,0 +1,94 @@
|
||||
(in-package :opencortex)
|
||||
|
||||
(defun utils-org-read-file (filepath)
|
||||
"Reads an Org file into a string."
|
||||
(uiop:read-file-string filepath))
|
||||
|
||||
(defun utils-org-write-file (filepath content)
|
||||
"Writes content to an Org file."
|
||||
(uiop:with-output-file (s filepath :if-exists :supersede)
|
||||
(format s "~a" content)))
|
||||
|
||||
(defun utils-org-generate-id ()
|
||||
"Generates a new UUID for an Org node."
|
||||
(string-downcase (format nil "~a" (uuid:make-v4-uuid))))
|
||||
|
||||
(defun utils-org-id-format (id)
|
||||
"Ensures the ID has the 'id:' prefix."
|
||||
(if (uiop:string-prefix-p "id:" id)
|
||||
id
|
||||
(format nil "id:~a" id)))
|
||||
|
||||
(defun utils-org-set-property (ast target-id property value)
|
||||
"Recursively sets a property on a headline with a matching ID in the AST."
|
||||
(let ((type (getf ast :type))
|
||||
(props (getf ast :properties))
|
||||
(contents (getf ast :contents)))
|
||||
(when (and (eq type :HEADLINE) (string= (getf props :ID) target-id))
|
||||
(setf (getf (getf ast :properties) property) value)
|
||||
(return-from utils-org-set-property t))
|
||||
(dolist (child contents)
|
||||
(when (listp child)
|
||||
(when (utils-org-set-property child target-id property value)
|
||||
(return-from utils-org-set-property t)))))
|
||||
nil)
|
||||
|
||||
(defun utils-org-set-todo (ast target-id status)
|
||||
"Sets the TODO status of a headline in the AST."
|
||||
(utils-org-set-property ast target-id :TODO status))
|
||||
|
||||
(defun utils-org-add-headline (ast parent-id title)
|
||||
"Adds a new headline as a child of the parent-id in the AST."
|
||||
(let ((type (getf ast :type))
|
||||
(props (getf ast :properties))
|
||||
(id (getf props :ID))
|
||||
(contents (getf ast :contents)))
|
||||
(when (and (eq type :HEADLINE) (string= id parent-id))
|
||||
(let ((new-node (list :type :HEADLINE
|
||||
:properties (list :ID (utils-org-id-format (utils-org-generate-id))
|
||||
:TITLE title)
|
||||
:contents nil)))
|
||||
(setf (getf ast :contents) (append contents (list new-node)))
|
||||
(return-from utils-org-add-headline t)))
|
||||
(dolist (child contents)
|
||||
(when (listp child)
|
||||
(when (utils-org-add-headline child parent-id title)
|
||||
(return-from utils-org-add-headline t)))))
|
||||
nil)
|
||||
|
||||
(defun utils-org-find-headline-by-id (ast id)
|
||||
"Finds a headline by its ID in the AST."
|
||||
(let ((props (getf ast :properties)))
|
||||
(when (string= (getf props :ID) id)
|
||||
(return-from utils-org-find-headline-by-id ast))
|
||||
(dolist (child (getf ast :contents))
|
||||
(when (listp child)
|
||||
(let ((found (utils-org-find-headline-by-id child id)))
|
||||
(when found (return-from utils-org-find-headline-by-id found)))))
|
||||
nil))
|
||||
|
||||
(defun utils-org-find-headline-by-title (ast title)
|
||||
"Finds a headline by its title in the AST."
|
||||
(let ((props (getf ast :properties)))
|
||||
(when (string-equal (getf props :TITLE) title)
|
||||
(return-from utils-org-find-headline-by-title ast))
|
||||
(dolist (child (getf ast :contents))
|
||||
(when (listp child)
|
||||
(let ((found (utils-org-find-headline-by-title child title)))
|
||||
(when found (return-from utils-org-find-headline-by-title found)))))
|
||||
nil))
|
||||
|
||||
(defun utils-org-modify (filepath id changes)
|
||||
"Placeholder for Emacs-driven modification of a specific node."
|
||||
(harness-log "UTILS-ORG: Applying changes to ~a in ~a" id filepath)
|
||||
(declare (ignore changes))
|
||||
t)
|
||||
|
||||
(defun utils-org-ast-to-org (ast)
|
||||
"Minimal converter from AST back to Org text (Placeholder)."
|
||||
(declare (ignore ast))
|
||||
"* TITLE (Placeholder)")
|
||||
|
||||
(defskill :skill-utils-org
|
||||
:priority 100
|
||||
:trigger (lambda (ctx) (declare (ignore ctx)) nil))
|
||||
Reference in New Issue
Block a user