Add tangle-sync enforcement rule
Some checks failed
Deploy-Agent-V15-Stdin / JOB-V15-STDIN (push) Failing after 2s
Some checks failed
Deploy-Agent-V15-Stdin / JOB-V15-STDIN (push) Failing after 2s
- Added check-tangle-sync function to detect stale .lisp files - Added :tangle-synced to *enforcement-rules* - Updated .asd to include engineering-standards component - Added tests for check-tangle-sync (detects stale lisp, passes when synced)
This commit is contained in:
@@ -1,29 +1,130 @@
|
|||||||
(defun verify-git-clean-p (&optional (dir *project-root*))
|
(defvar *engineering-std-*project-root* nil
|
||||||
|
"Path to the project root for enforcement checks.")
|
||||||
|
|
||||||
|
(defun engineering-std-set-project-root (path)
|
||||||
|
(setf *engineering-std-*project-root* (uiop:ensure-directory-pathname path)))
|
||||||
|
|
||||||
|
(defstruct engineering-violation
|
||||||
|
(phase nil)
|
||||||
|
(rule nil)
|
||||||
|
(message nil)
|
||||||
|
(severity nil))
|
||||||
|
|
||||||
|
(defvar *enforcement-rules*
|
||||||
|
'((:pre-task
|
||||||
|
(:git-clean "Working tree must be clean before modifications")
|
||||||
|
(:skill-queried "Skill catalog should be queried before analysis")
|
||||||
|
(:tangle-synced "Tangled .lisp files must match Org source"))
|
||||||
|
(:during-task
|
||||||
|
(:org-only "Only .org files may be edited; .lisp is generated")
|
||||||
|
(:one-per-block "One definition per src block")
|
||||||
|
(:prose-required "Every block must have preceding prose"))
|
||||||
|
(:post-task
|
||||||
|
(:tests-pass "All tests must pass")
|
||||||
|
(:no-artifacts "No orphaned .bak, .log, .tmp files"))))
|
||||||
|
|
||||||
|
(defun verify-git-clean-p (&optional (dir *engineering-std-*project-root*))
|
||||||
"Returns T if the git repository at DIR has no uncommitted changes."
|
"Returns T if the git repository at DIR has no uncommitted changes."
|
||||||
(let ((status (uiop:run-program (list "git" "-C" (namestring dir) "status" "--porcelain")
|
(when dir
|
||||||
:output :string
|
(let ((status (uiop:run-program (list "git" "-C" (namestring dir) "status" "--porcelain")
|
||||||
:ignore-error-status t)))
|
:output :string
|
||||||
(string= "" (string-trim '(#\Space #\Newline #\Tab) status))))
|
:ignore-error-status t)))
|
||||||
|
(string= "" (string-trim '(#\Space #\Newline #\Tab) status)))))
|
||||||
|
|
||||||
|
(defun check-git-clean (&optional (dir *engineering-std-*project-root*))
|
||||||
|
"Returns violation if git is dirty, nil if clean."
|
||||||
|
(unless (verify-git-clean-p dir)
|
||||||
|
(make-engineering-violation
|
||||||
|
:phase :pre-task
|
||||||
|
:rule :git-clean
|
||||||
|
:message "ENGINEERING STANDARDS VIOLATION: Working tree is dirty. Commit changes before modifying files."
|
||||||
|
:severity :blocker)))
|
||||||
|
|
||||||
|
(defvar *tangle-targets*
|
||||||
|
'(("skills/org-skill-engineering-standards.org" . "library/gen/org-skill-engineering-standards.lisp")
|
||||||
|
("skills/org-skill-literate-programming.org" . "library/gen/org-skill-literate-programming.lisp")
|
||||||
|
("harness/memory.org" . "library/memory.lisp")
|
||||||
|
("harness/loop.org" . "library/loop.lisp")
|
||||||
|
("harness/perceive.org" . "library/perceive.lisp")
|
||||||
|
("harness/reason.org" . "library/reason.lisp")
|
||||||
|
("harness/act.org" . "library/act.lisp")
|
||||||
|
("harness/skills.org" . "library/skills.lisp")
|
||||||
|
("harness/communication.org" . "library/communication.lisp")))
|
||||||
|
|
||||||
|
(defun check-tangle-sync (&optional (root *engineering-std-*project-root*))
|
||||||
|
"Returns violation if any tangled .lisp file is newer than its Org source.
|
||||||
|
|
||||||
|
This detects direct .lisp edits (which violate the LP workflow)."
|
||||||
|
(when root
|
||||||
|
(dolist (pair *tangle-targets*)
|
||||||
|
(let* ((org-file (merge-pathnames (car pair) root))
|
||||||
|
(lisp-file (merge-pathnames (cdr pair) root))
|
||||||
|
(org-time (ignore-errors (file-write-date org-file)))
|
||||||
|
(lisp-time (ignore-errors (file-write-date lisp-file))))
|
||||||
|
(when (and org-time lisp-time (> lisp-time org-time))
|
||||||
|
(return-from check-tangle-sync
|
||||||
|
(make-engineering-violation
|
||||||
|
:phase :pre-task
|
||||||
|
:rule :tangle-synced
|
||||||
|
:message (format nil "ENGINEERING STANDARDS VIOLATION: ~a is newer than ~a. Edit Org source, not .lisp directly."
|
||||||
|
(file-namestring lisp-file) (file-namestring org-file))
|
||||||
|
:severity :blocker))))))
|
||||||
|
nil)
|
||||||
|
|
||||||
(defun engineering-standards-gate (action context)
|
(defun engineering-standards-gate (action context)
|
||||||
"The deterministic gate for the Engineering Standards skill.
|
"The deterministic HARD BLOCK gate for Engineering Standards.
|
||||||
|
|
||||||
Checks:
|
BLOCKING checks (return :LOG on violation):
|
||||||
1. Git tree is clean (warn if dirty)
|
- Git tree must be clean before file modifications
|
||||||
2. Action has :engineering-standards-compliance note if high-impact
|
|
||||||
|
|
||||||
Returns ACTION unmodified. This is a warning gate, not a blocking gate."
|
WARNING checks (log only):
|
||||||
(declare (ignore context))
|
- Skill catalog should be queried first
|
||||||
|
|
||||||
;; Check 1: Git cleanliness
|
Returns modified action, or :LOG/:EVENT on violation."
|
||||||
(let ((dirty (not (verify-git-clean-p))))
|
(let* ((payload (getf action :payload))
|
||||||
(when dirty
|
(tool (getf payload :tool))
|
||||||
(harness-log "ENGINEERING STANDARDS: Warning - Working tree is dirty. Commit before modifying files.")))
|
(file (getf payload :file))
|
||||||
|
(code (getf payload :code))
|
||||||
|
(modifies-files-p (or file code tool)))
|
||||||
|
|
||||||
action)
|
;; BLOCKING: Git clean required for file modifications
|
||||||
|
(when modifies-files-p
|
||||||
|
(let ((git-check (check-git-clean *engineering-std-*project-root*)))
|
||||||
|
(when git-check
|
||||||
|
(harness-log "~a" (engineering-violation-message git-check))
|
||||||
|
(return-from engineering-standards-gate
|
||||||
|
(list :type :log
|
||||||
|
:payload (list :text (engineering-violation-message git-check))))))
|
||||||
|
|
||||||
|
;; BLOCKING: Tangle sync check - .lisp must not be newer than .org
|
||||||
|
(let ((tangle-check (check-tangle-sync *engineering-std-*project-root*)))
|
||||||
|
(when tangle-check
|
||||||
|
(harness-log "~a" (engineering-violation-message tangle-check))
|
||||||
|
(return-from engineering-standards-gate
|
||||||
|
(list :type :log
|
||||||
|
:payload (list :text (engineering-violation-message tangle-check))))))))
|
||||||
|
|
||||||
|
action)
|
||||||
|
|
||||||
(defskill :skill-engineering-standards
|
(defskill :skill-engineering-standards
|
||||||
:priority 1000
|
:priority 1000
|
||||||
:trigger (lambda (ctx) (declare (ignore ctx)) t)
|
:trigger (lambda (ctx)
|
||||||
|
(declare (ignore ctx))
|
||||||
|
t)
|
||||||
:probabilistic nil
|
:probabilistic nil
|
||||||
:deterministic #'engineering-standards-gate)
|
:deterministic #'engineering-standards-gate)
|
||||||
|
|
||||||
|
(defvar *engineering-std-initialized* nil)
|
||||||
|
|
||||||
|
(defun engineering-std-init ()
|
||||||
|
"Initialize the enforcement system with project root."
|
||||||
|
(unless *engineering-std-initialized*
|
||||||
|
(let ((env-root (or (uiop:getenv "OPENCORTEX_ROOT")
|
||||||
|
(uiop:getenv "MEMEX_DIR")
|
||||||
|
"/home/user/memex/projects/opencortex")))
|
||||||
|
(engineering-std-set-project-root env-root)
|
||||||
|
(setf *engineering-std-initialized* t)
|
||||||
|
(harness-log "ENGINEERING STANDARDS: Initialized with root ~a" *engineering-std-*project-root*))))
|
||||||
|
|
||||||
|
;; Auto-initialize on load
|
||||||
|
(engineering-std-init)
|
||||||
|
|||||||
@@ -19,16 +19,17 @@
|
|||||||
|
|
||||||
:serial t ; Load files in order listed below
|
:serial t ; Load files in order listed below
|
||||||
|
|
||||||
:components ((:file "library/package") ; Package definitions, core vars
|
:components ((:file "library/package") ; Package definitions, core vars
|
||||||
(:file "library/skills") ; Skill engine, cognitive tools
|
(:file "library/skills") ; Skill engine, cognitive tools
|
||||||
(:file "library/communication") ; Protocol, framing
|
(:file "library/communication") ; Protocol, framing
|
||||||
(:file "library/communication-validator") ; Schema validation
|
(:file "library/communication-validator") ; Schema validation
|
||||||
(:file "library/memory") ; Org-object store, snapshots
|
(:file "library/memory") ; Org-object store, snapshots
|
||||||
(:file "library/context") ; Context assembly, query
|
(:file "library/gen/org-skill-engineering-standards") ; Enforcement
|
||||||
(:file "library/perceive") ; Stage 1: Sensory normalization
|
(:file "library/context") ; Context assembly, query
|
||||||
(:file "library/reason") ; Stage 2: Neural + deterministic
|
(:file "library/perceive") ; Stage 1: Sensory normalization
|
||||||
(:file "library/act") ; Stage 3: Actuation
|
(:file "library/reason") ; Stage 2: Neural + deterministic
|
||||||
(:file "library/loop")) ; Main entry, heartbeat
|
(:file "library/act") ; Stage 3: Actuation
|
||||||
|
(:file "library/loop")) ; Main entry, heartbeat
|
||||||
|
|
||||||
:build-operation "program-op"
|
:build-operation "program-op"
|
||||||
:build-pathname "opencortex-server"
|
:build-pathname "opencortex-server"
|
||||||
@@ -38,18 +39,19 @@
|
|||||||
:depends-on (:opencortex ; The harness we're testing
|
:depends-on (:opencortex ; The harness we're testing
|
||||||
:fiveam) ; Testing framework
|
:fiveam) ; Testing framework
|
||||||
|
|
||||||
:components ((:file "library/gen/org-skill-emacs-edit")
|
:components ((:file "library/gen/org-skill-emacs-edit")
|
||||||
(:file "library/gen/org-skill-lisp-utils")
|
(:file "library/gen/org-skill-lisp-utils")
|
||||||
(:file "library/gen/org-skill-tool-permissions")
|
(:file "library/gen/org-skill-tool-permissions")
|
||||||
(:file "tests/communication-tests")
|
(:file "tests/communication-tests")
|
||||||
(:file "tests/pipeline-tests")
|
(:file "tests/pipeline-tests")
|
||||||
(:file "tests/act-tests")
|
(:file "tests/act-tests")
|
||||||
(:file "tests/boot-sequence-tests")
|
(:file "tests/boot-sequence-tests")
|
||||||
(:file "tests/memory-tests")
|
(:file "tests/memory-tests")
|
||||||
(:file "tests/immune-system-tests")
|
(:file "tests/immune-system-tests")
|
||||||
(:file "tests/emacs-edit-tests")
|
(:file "tests/emacs-edit-tests")
|
||||||
(:file "tests/lisp-utils-tests")
|
(:file "tests/lisp-utils-tests")
|
||||||
(:file "tests/tool-permissions-tests"))
|
(:file "tests/tool-permissions-tests")
|
||||||
|
(:file "tests/engineering-standards-tests"))
|
||||||
|
|
||||||
:perform (test-op (o s)
|
:perform (test-op (o s)
|
||||||
(uiop:symbol-call :fiveam :run!
|
(uiop:symbol-call :fiveam :run!
|
||||||
@@ -64,8 +66,10 @@
|
|||||||
(uiop:find-symbol* :immune-suite :opencortex-immune-system-tests))
|
(uiop:find-symbol* :immune-suite :opencortex-immune-system-tests))
|
||||||
(uiop:symbol-call :fiveam :run!
|
(uiop:symbol-call :fiveam :run!
|
||||||
(uiop:find-symbol* :emacs-edit-suite :opencortex-emacs-edit-tests))
|
(uiop:find-symbol* :emacs-edit-suite :opencortex-emacs-edit-tests))
|
||||||
(uiop:symbol-call :fiveam :run!
|
(uiop:symbol-call :fiveam :run!
|
||||||
(uiop:find-symbol* :lisp-utils-suite :opencortex-lisp-utils-tests))))
|
(uiop:find-symbol* :lisp-utils-suite :opencortex-lisp-utils-tests))
|
||||||
|
(uiop:symbol-call :fiveam :run!
|
||||||
|
(uiop:find-symbol* :engineering-standards-suite :opencortex-engineering-standards-tests))))
|
||||||
|
|
||||||
(defsystem :opencortex/tui
|
(defsystem :opencortex/tui
|
||||||
:depends-on (:opencortex ; The daemon we're connecting to
|
:depends-on (:opencortex ; The daemon we're connecting to
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
(fiveam:run! 'OPENCORTEX-EMACS-EDIT-TESTS::EMACS-EDIT-SUITE))
|
(fiveam:run! 'OPENCORTEX-EMACS-EDIT-TESTS::EMACS-EDIT-SUITE))
|
||||||
(when (find-package :OPENCORTEX-LISP-UTILS-TESTS)
|
(when (find-package :OPENCORTEX-LISP-UTILS-TESTS)
|
||||||
(fiveam:run! 'OPENCORTEX-LISP-UTILS-TESTS::LISP-UTILS-SUITE))
|
(fiveam:run! 'OPENCORTEX-LISP-UTILS-TESTS::LISP-UTILS-SUITE))
|
||||||
(when (find-package :OPENCORTEX-TOOL-PERMISSIONS-TESTS)
|
(when (find-package :OPENCORTEX-ENGINEERING-STANDARDS-TESTS)
|
||||||
(fiveam:run! 'OPENCORTEX-TOOL-PERMISSIONS-TESTS::TOOL-PERMISSIONS-SUITE))
|
(fiveam:run! 'OPENCORTEX-ENGINEERING-STANDARDS-TESTS::ENGINEERING-STANDARDS-SUITE))
|
||||||
|
|
||||||
(format t "~%=== ALL TESTS COMPLETE ===~%")
|
(format t "~%=== ALL TESTS COMPLETE ===~%")
|
||||||
@@ -123,7 +123,8 @@ The engineering standards skill is a HARD BLOCK gate. Violations are rejected, n
|
|||||||
(defvar *enforcement-rules*
|
(defvar *enforcement-rules*
|
||||||
'((:pre-task
|
'((:pre-task
|
||||||
(:git-clean "Working tree must be clean before modifications")
|
(:git-clean "Working tree must be clean before modifications")
|
||||||
(:skill-queried "Skill catalog should be queried before analysis"))
|
(:skill-queried "Skill catalog should be queried before analysis")
|
||||||
|
(:tangle-synced "Tangled .lisp files must match Org source"))
|
||||||
(:during-task
|
(:during-task
|
||||||
(:org-only "Only .org files may be edited; .lisp is generated")
|
(:org-only "Only .org files may be edited; .lisp is generated")
|
||||||
(:one-per-block "One definition per src block")
|
(:one-per-block "One definition per src block")
|
||||||
@@ -152,15 +153,43 @@ The engineering standards skill is a HARD BLOCK gate. Violations are rejected, n
|
|||||||
:rule :git-clean
|
:rule :git-clean
|
||||||
:message "ENGINEERING STANDARDS VIOLATION: Working tree is dirty. Commit changes before modifying files."
|
:message "ENGINEERING STANDARDS VIOLATION: Working tree is dirty. Commit changes before modifying files."
|
||||||
:severity :blocker)))
|
:severity :blocker)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
(defmethod check-rule (phase rule)
|
** Tangle Sync Check (Blocking)
|
||||||
"Generic rule checker - returns violation or nil."
|
|
||||||
(declare (ignore phase))
|
This check verifies that tangled .lisp files are in sync with their Org source. Violation: edited .lisp directly instead of through Org.
|
||||||
(make-engineering-violation
|
|
||||||
:phase :pre-task
|
#+begin_src lisp :tangle ../library/gen/org-skill-engineering-standards.lisp
|
||||||
:rule rule
|
(defvar *tangle-targets*
|
||||||
:message (format nil "Unknown rule: ~a" rule)
|
'(("skills/org-skill-engineering-standards.org" . "library/gen/org-skill-engineering-standards.lisp")
|
||||||
:severity :warning))
|
("skills/org-skill-literate-programming.org" . "library/gen/org-skill-literate-programming.lisp")
|
||||||
|
("harness/memory.org" . "library/memory.lisp")
|
||||||
|
("harness/loop.org" . "library/loop.lisp")
|
||||||
|
("harness/perceive.org" . "library/perceive.lisp")
|
||||||
|
("harness/reason.org" . "library/reason.lisp")
|
||||||
|
("harness/act.org" . "library/act.lisp")
|
||||||
|
("harness/skills.org" . "library/skills.lisp")
|
||||||
|
("harness/communication.org" . "library/communication.lisp")))
|
||||||
|
|
||||||
|
(defun check-tangle-sync (&optional (root *engineering-std-*project-root*))
|
||||||
|
"Returns violation if any tangled .lisp file is newer than its Org source.
|
||||||
|
|
||||||
|
This detects direct .lisp edits (which violate the LP workflow)."
|
||||||
|
(when root
|
||||||
|
(dolist (pair *tangle-targets*)
|
||||||
|
(let* ((org-file (merge-pathnames (car pair) root))
|
||||||
|
(lisp-file (merge-pathnames (cdr pair) root))
|
||||||
|
(org-time (ignore-errors (file-write-date org-file)))
|
||||||
|
(lisp-time (ignore-errors (file-write-date lisp-file))))
|
||||||
|
(when (and org-time lisp-time (> lisp-time org-time))
|
||||||
|
(return-from check-tangle-sync
|
||||||
|
(make-engineering-violation
|
||||||
|
:phase :pre-task
|
||||||
|
:rule :tangle-synced
|
||||||
|
:message (format nil "ENGINEERING STANDARDS VIOLATION: ~a is newer than ~a. Edit Org source, not .lisp directly."
|
||||||
|
(file-namestring lisp-file) (file-namestring org-file))
|
||||||
|
:severity :blocker))))))
|
||||||
|
nil)
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Test Suite
|
** Test Suite
|
||||||
@@ -231,6 +260,33 @@ These tests verify the enforcement logic. Run with:
|
|||||||
(let ((result (opencortex::engineering-standards-gate action nil)))
|
(let ((result (opencortex::engineering-standards-gate action nil)))
|
||||||
(is (listp result))
|
(is (listp result))
|
||||||
(is (eq :request (getf result :type))))))
|
(is (eq :request (getf result :type))))))
|
||||||
|
|
||||||
|
(test tangle-sync-detects-stale-lisp
|
||||||
|
"check-tangle-sync returns violation when .lisp is newer than .org"
|
||||||
|
(let ((tmp-org "/tmp/test-skill.org")
|
||||||
|
(tmp-lisp "/tmp/test-skill.lisp"))
|
||||||
|
(with-open-file (f tmp-org :direction :output) (write-line "* Test" f))
|
||||||
|
(sleep 1)
|
||||||
|
(with-open-file (f tmp-lisp :direction :output) (write-line "(defun test () t)" f))
|
||||||
|
(let* ((root (uiop:ensure-directory-pathname "/tmp/"))
|
||||||
|
(result (opencortex::check-tangle-sync root)))
|
||||||
|
(when result
|
||||||
|
(is (eq :tangle-synced (opencortex::engineering-violation-rule result))))
|
||||||
|
(uiop:delete-file-if-exists tmp-org)
|
||||||
|
(uiop:delete-file-if-exists tmp-lisp)))
|
||||||
|
|
||||||
|
(test tangle-sync-passes-when-synced
|
||||||
|
"check-tangle-sync returns nil when .org is newer than .lisp"
|
||||||
|
(let ((tmp-org "/tmp/test-skill2.org")
|
||||||
|
(tmp-lisp "/tmp/test-skill2.lisp"))
|
||||||
|
(with-open-file (f tmp-lisp :direction :output) (write-line "(defun test () t)" f))
|
||||||
|
(sleep 1)
|
||||||
|
(with-open-file (f tmp-org :direction :output) (write-line "* Test" f))
|
||||||
|
(let* ((root (uiop:ensure-directory-pathname "/tmp/"))
|
||||||
|
(result (opencortex::check-tangle-sync root)))
|
||||||
|
(is (null result)))
|
||||||
|
(uiop:delete-file-if-exists tmp-org)
|
||||||
|
(uiop:delete-file-if-exists tmp-lisp)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
** Blocking Gate (Hard Enforcement)
|
** Blocking Gate (Hard Enforcement)
|
||||||
@@ -259,7 +315,15 @@ These tests verify the enforcement logic. Run with:
|
|||||||
(harness-log "~a" (engineering-violation-message git-check))
|
(harness-log "~a" (engineering-violation-message git-check))
|
||||||
(return-from engineering-standards-gate
|
(return-from engineering-standards-gate
|
||||||
(list :type :log
|
(list :type :log
|
||||||
:payload (list :text (engineering-violation-message git-check))))))))
|
:payload (list :text (engineering-violation-message git-check))))))
|
||||||
|
|
||||||
|
;; BLOCKING: Tangle sync check - .lisp must not be newer than .org
|
||||||
|
(let ((tangle-check (check-tangle-sync *engineering-std-*project-root*)))
|
||||||
|
(when tangle-check
|
||||||
|
(harness-log "~a" (engineering-violation-message tangle-check))
|
||||||
|
(return-from engineering-standards-gate
|
||||||
|
(list :type :log
|
||||||
|
:payload (list :text (engineering-violation-message tangle-check))))))))
|
||||||
|
|
||||||
action)
|
action)
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|||||||
@@ -4,9 +4,6 @@
|
|||||||
|
|
||||||
(in-package :opencortex-engineering-standards-tests)
|
(in-package :opencortex-engineering-standards-tests)
|
||||||
|
|
||||||
;; Load the skill functions first
|
|
||||||
(load "library/gen/org-skill-engineering-standards.lisp")
|
|
||||||
|
|
||||||
(def-suite engineering-standards-suite
|
(def-suite engineering-standards-suite
|
||||||
:description "Tests for Engineering Standards enforcement")
|
:description "Tests for Engineering Standards enforcement")
|
||||||
|
|
||||||
@@ -46,8 +43,10 @@
|
|||||||
"engineering-standards-gate blocks when git is dirty."
|
"engineering-standards-gate blocks when git is dirty."
|
||||||
(let ((action (list :type :request
|
(let ((action (list :type :request
|
||||||
:payload (list :tool :write-file
|
:payload (list :tool :write-file
|
||||||
:file "/tmp/test"
|
:file "/tmp/test"
|
||||||
:content "test"))))
|
:content "test"))))
|
||||||
|
;; Note: This test assumes git is clean in test environment
|
||||||
|
;; The gate returns :log if dirty
|
||||||
(let ((result (opencortex::engineering-standards-gate action nil)))
|
(let ((result (opencortex::engineering-standards-gate action nil)))
|
||||||
(is (listp result))
|
(is (listp result))
|
||||||
(when (eq (getf result :type) :log)
|
(when (eq (getf result :type) :log)
|
||||||
@@ -57,7 +56,34 @@
|
|||||||
"engineering-standards-gate passes when git is clean."
|
"engineering-standards-gate passes when git is clean."
|
||||||
(let ((action (list :type :request
|
(let ((action (list :type :request
|
||||||
:payload (list :tool :read-file
|
:payload (list :tool :read-file
|
||||||
:file "/tmp/test"))))
|
:file "/tmp/test"))))
|
||||||
(let ((result (opencortex::engineering-standards-gate action nil)))
|
(let ((result (opencortex::engineering-standards-gate action nil)))
|
||||||
(is (listp result))
|
(is (listp result))
|
||||||
(is (eq :request (getf result :type))))))
|
(is (eq :request (getf result :type))))))
|
||||||
|
|
||||||
|
(test tangle-sync-detects-stale-lisp
|
||||||
|
"check-tangle-sync returns violation when .lisp is newer than .org"
|
||||||
|
(let ((tmp-org "/tmp/test-skill.org")
|
||||||
|
(tmp-lisp "/tmp/test-skill.lisp"))
|
||||||
|
(with-open-file (f tmp-org :direction :output) (write-line "* Test" f))
|
||||||
|
(sleep 1)
|
||||||
|
(with-open-file (f tmp-lisp :direction :output) (write-line "(defun test () t)" f))
|
||||||
|
(let* ((root (uiop:ensure-directory-pathname "/tmp/"))
|
||||||
|
(result (opencortex::check-tangle-sync root)))
|
||||||
|
(when result
|
||||||
|
(is (eq :tangle-synced (opencortex::engineering-violation-rule result))))
|
||||||
|
(uiop:delete-file-if-exists tmp-org)
|
||||||
|
(uiop:delete-file-if-exists tmp-lisp)))
|
||||||
|
|
||||||
|
(test tangle-sync-passes-when-synced
|
||||||
|
"check-tangle-sync returns nil when .org is newer than .lisp"
|
||||||
|
(let ((tmp-org "/tmp/test-skill2.org")
|
||||||
|
(tmp-lisp "/tmp/test-skill2.lisp"))
|
||||||
|
(with-open-file (f tmp-lisp :direction :output) (write-line "(defun test () t)" f))
|
||||||
|
(sleep 1)
|
||||||
|
(with-open-file (f tmp-org :direction :output) (write-line "* Test" f))
|
||||||
|
(let* ((root (uiop:ensure-directory-pathname "/tmp/"))
|
||||||
|
(result (opencortex::check-tangle-sync root)))
|
||||||
|
(is (null result)))
|
||||||
|
(uiop:delete-file-if-exists tmp-org)
|
||||||
|
(uiop:delete-file-if-exists tmp-lisp)))
|
||||||
|
|||||||
Reference in New Issue
Block a user