- 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)
15 KiB
SKILL: Engineering Standards
- Overview
- Phase 0: Before You Think
- Phase A: Design (Test-First)
- Phase B: Commit (Recovery Point)
- Phase C: Build (Implementation)
- Phase D: Validate (Proof)
- Phase E: Document (Audit Trail)
- Enforcement Implementation
- See Also
Overview
This skill enforces the Engineering Standards for all development within OpenCortex. It observes agent context and gates actions that violate protocol.
The standards are ordered by lifecycle phase, not priority. An agent must execute them in sequence, not selectively.
Phase 0: Before You Think
Skill-First Query Rule
Before any analysis, debugging, or implementation: check if a skill already covers the problem domain.
Query the skill catalog via (list-skills) or (find-skill :keyword). If a relevant skill exists:
- Read the skill's org file
- Follow its mandates
- Do not duplicate logic
Rationale: The skill layer is the primary intelligence. Raw LLM reasoning is a fallback, not a starting point. Violating this creates drift, where your solution diverges from the system's encoded wisdom.
Phase A: Design (Test-First)
1. Define Success Criteria First
Before writing code, write the test that proves the feature works. The test defines the contract.
If the change is architectural, write the test as a PROTOCOL document (Plan Mode) and seek approval.
2. Break the Design with Chaos
After defining success criteria, run adversarial analysis:
- Deterministic chaos: Scripted regression tests that feed the system known-good inputs and verify known-good outputs. Run on every change.
- Probabilistic chaos: Randomized fuzzing, property-based testing, and noise injection to discover unknown failure modes. Run on every major release.
- Stress chaos: Sustained load, resource starvation, and concurrent access to find edge-case instabilities. Run during hardening sprints.
Rationale: If you cannot break your own design, you have not understood it.
Phase B: Commit (Recovery Point)
3. Commit Before Modify
You MUST commit (and push, if network is available) the current workspace state before initiating new file modifications.
This is not a suggestion. If verify-git-clean-p returns NIL, the engineering standards gate MAY block high-impact actions.
Phase C: Build (Implementation)
4. Literate Programming (Single Source of Truth)
All system logic and skills MUST be implemented as Literate Org files. Weave documentation and code together. The "Why" (Architectural Intent) is never separated from the "How" (Implementation).
5. Function-Block Granularity
Every Lisp function, macro, or variable resides in its own dedicated #+begin_src lisp block, immediately preceded by its explanatory text.
6. Tangle Mandate
You are forbidden from modifying generated .lisp files directly. All changes MUST be made in the Org file and then tangled.
7. Configuration Externalization
Source code MUST be free of hardcoded configuration values. Extract to environment variables and document in .env.example.
8. Org as Thinking Medium
When debugging or analyzing issues, document your investigation in the relevant org file BEFORE implementing a fix.
Record: root cause hypothesis, evidence found, options considered, tradeoffs, decision rationale.
Phase D: Validate (Proof)
9. Test Verification
No change is complete without running the test suite. A change that breaks existing tests is not a fix — it is damage.
Run chaotic tests alongside the main suite.
Phase E: Document (Audit Trail)
10. Decision Audit Trail
Every significant fix or architectural decision MUST be documented in an org file with:
- Root cause analysis
- Options considered and tradeoffs
- Why this solution was chosen
11. Stop-and-Wait (Turn-Yielding)
For major changes, propose your strategy in plain text, state "Waiting for user feedback," and yield the turn. Do not draft implementation in the same message.
12. GTD Synchronization
You are forbidden from considering a task complete without updating gtd.org. Record all major shifts using hierarchical TODO headlines, NOT checkboxes.
Enforcement Implementation
The engineering standards skill is a HARD BLOCK gate. Violations are rejected, not warned.
Pre-Task Enforcement (Blocking)
(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"))))
Git Clean Check (Blocking)
(defun verify-git-clean-p (&optional (dir *engineering-std-*project-root*))
"Returns T if the git repository at DIR has no uncommitted changes."
(when dir
(let ((status (uiop:run-program (list "git" "-C" (namestring dir) "status" "--porcelain")
:output :string
: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)))
Tangle Sync Check (Blocking)
This check verifies that tangled .lisp files are in sync with their Org source. Violation: edited .lisp directly instead of through Org.
(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)
Test Suite
These tests verify the enforcement logic. Run with:
(fiveam:run! 'engineering-standards-suite)
(defpackage :opencortex-engineering-standards-tests
(:use :cl :fiveam :opencortex)
(:export #:engineering-standards-suite))
(in-package :opencortex-engineering-standards-tests)
(def-suite engineering-standards-suite
:description "Tests for Engineering Standards enforcement")
(in-suite engineering-standards-suite)
(test git-clean-check-clean
"verify-git-clean-p returns T when git tree is clean."
(let ((tmp-dir "/tmp/eng-std-test-clean/"))
(uiop:ensure-all-directories-exist (list tmp-dir))
(uiop:run-program (list "git" "init" tmp-dir) :output nil)
(is (eq t (opencortex::verify-git-clean-p (uiop:ensure-directory-pathname tmp-dir))))
(uiop:delete-directory-tree (uiop:ensure-directory-pathname tmp-dir) :validate t)))
(test git-clean-check-dirty
"verify-git-clean-p returns NIL when git tree has uncommitted changes."
(let ((tmp-dir "/tmp/eng-std-test-dirty/"))
(uiop:ensure-all-directories-exist (list tmp-dir))
(uiop:run-program (list "git" "init" tmp-dir) :output nil)
(with-open-file (f (merge-pathnames "test.txt" tmp-dir) :direction :output)
(write-line "test" f))
(is (null (opencortex::verify-git-clean-p (uiop:ensure-directory-pathname tmp-dir))))
(uiop:delete-directory-tree (uiop:ensure-directory-pathname tmp-dir) :validate t)))
(test violation-struct
"engineering-violation struct is properly constructed."
(let ((v (opencortex::make-engineering-violation
:phase :pre-task
:rule :git-clean
:message "Test violation"
:severity :blocker)))
(is (eq :pre-task (opencortex::engineering-violation-phase v)))
(is (eq :git-clean (opencortex::engineering-violation-rule v)))
(is (string= "Test violation" (opencortex::engineering-violation-message v)))
(is (eq :blocker (opencortex::engineering-violation-severity v)))))
(test gate-blocks-dirty-tree
"engineering-standards-gate blocks when git is dirty."
(let ((action (list :type :request
:payload (list :tool :write-file
:file "/tmp/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)))
(is (listp result))
(when (eq (getf result :type) :log)
(is (search "dirty" (getf (getf result :payload) :text) :test #'char-equal))))))
(test gate-allows-clean-tree
"engineering-standards-gate passes when git is clean."
(let ((action (list :type :request
:payload (list :tool :read-file
:file "/tmp/test"))))
(let ((result (opencortex::engineering-standards-gate action nil)))
(is (listp result))
(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)))
Blocking Gate (Hard Enforcement)
(defun engineering-standards-gate (action context)
"The deterministic HARD BLOCK gate for Engineering Standards.
BLOCKING checks (return :LOG on violation):
- Git tree must be clean before file modifications
WARNING checks (log only):
- Skill catalog should be queried first
Returns modified action, or :LOG/:EVENT on violation."
(let* ((payload (getf action :payload))
(tool (getf payload :tool))
(file (getf payload :file))
(code (getf payload :code))
(modifies-files-p (or file code tool)))
;; 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)
Skill Registration
The skill runs at highest priority (1000) to block violations before any other skill.
(defskill :skill-engineering-standards
:priority 1000
:trigger (lambda (ctx)
(declare (ignore ctx))
t)
:probabilistic nil
:deterministic #'engineering-standards-gate)
Initialize Project Root
(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)
See Also
- Literate Programming Skill - Structural validation and tangle rules
- Policy Skill - Constitutional constraints
- opencortex README