Files
passepartout/org/programming-literate.org
Amr Gharbeia 5a0d1b1c38 remediation: backfill v0.1.0/v0.2.0 gaps (P0+P1)
- vault: add vault-get-secret/vault-set-secret wrappers
- programming-org: implement org-modify (text search-replace) and org-ast-render (AST to Org text)
- programming-literate: implement literate-block-balance-check (paren validation) and literate-tangle-sync-check (org→lisp diff)
- system-self-improve: replace stubs with surgical text editing and error diagnosis; remove dead first defskill
- system-event-orchestrator: implement orchestrator-bootstrap (scan Org files for HOOK/CRON)
- system-archivist: implement Scribe distillation (daily logs→atomic notes) and Gardener link/orphan repair
- system-memory: implement memory-inspect with type/todo/orphan statistics
- core-skills, core-context: fix path relic (skills/ → lisp/, org/)
- docs: add Token Economics section to DESIGN_DECISIONS, remediation roadmap entries
2026-05-03 10:43:14 -04:00

5.0 KiB

SKILL: Literate Programming (org-skill-literate-programming.org)

Overview

This skill enforces the literal programming discipline for all Passepartout source code. It defines the rules for one-function-per-block, prose-before-code, reflecting working code back from the REPL to Org, and the tangle mandate (never edit .lisp directly). Every Org file that contains Lisp code should follow the rules defined here.

Discipline Rules

One Function, One Block

Every #+begin_src lisp block contains exactly one function definition. Never bundle multiple definitions in a single block. This keeps the Org file granular, reviewable, and tanglable without side effects.

Prose Before Code

Every block must be preceded by an Org headline and explanatory prose that covers:

  • What the function does
  • Its arguments (including any &key, &optional)
  • Its return value
  • The rationale for its existence

The prose is not a comment — it is the authoritative specification. The code implements what the prose describes.

Reflect Back, Don't Write Directly

Code is explored and verified in the REPL first (per Engineering Standards lifecycle). Once working, it is reflected back into the Org file. This means:

  • The REPL is the proving ground — iterate there
  • The Org file is the record — copy working code there
  • Never write code directly into an Org block without first evaluating it in the REPL

Code and Prose Together

Every #+begin_src lisp block flows from the prose above it. The reader (human or agent) should understand the function's contract from the prose before reading the code. If the code and prose disagree, the prose is wrong — update both.

Tangle Mandate

The `.lisp` file is derived, not authored. Never edit `.lisp` directly. All changes flow through Org: edit Org → tangle → `.lisp` updates. Violating this corrupts the skill loader and causes boot failure.

Implementation

Block Extraction

(defun literate-extract-lisp-blocks (content)
  "Extracts all #+begin_src lisp ... #+end_src blocks from Org CONTENT.
Returns a list of block strings."
  (let ((lines (uiop:split-string content :separator '(#\Newline)))
        (blocks nil)
        (in-block nil)
        (current-block nil))
    (dolist (line lines)
      (let ((trimmed (string-trim '(#\Space) line)))
        (cond
          ((uiop:string-prefix-p "#+begin_src lisp" trimmed)
           (setf in-block t current-block nil))
          ((uiop:string-prefix-p "#+end_src" trimmed)
           (when in-block
             (push (format nil "~{~a~^~%~}" (nreverse current-block)) blocks)
             (setf in-block nil current-block nil)))
          (in-block
           (push line current-block)))))
    (nreverse blocks)))

Synchronization Logic

(defun literate-block-balance-check (org-file)
  "Verifies that all Lisp source blocks in an Org file have balanced parentheses.
Returns T if all blocks pass validation, or an error string listing failures."
  (when (not (uiop:file-exists-p org-file))
    (return-from literate-block-balance-check
      (format nil "Org file not found: ~a" org-file)))
  (let* ((content (uiop:read-file-string org-file))
         (blocks (literate-extract-lisp-blocks content))
         (failures nil))
    (if (null blocks)
        t
        (progn
          (loop for i from 0
                for block in blocks
                for (ok reason) = (multiple-value-list
                                    (lisp-structural-check block))
                unless ok
                do (push (format nil "Block ~d: ~a" (1+ i) reason) failures))
          (if failures
              (format nil "Unbalanced blocks in ~a:~%~{~a~^~%~}" org-file failures)
              t)))))

(defun literate-tangle-sync-check (org-file lisp-file)
  "Verifies that the .lisp file matches the tangled output of the .org file.
Compares the concatenation of all lisp blocks from the Org file against the
contents of the Lisp file. Returns T if they match, or an error message."
  (when (not (uiop:file-exists-p org-file))
    (return-from literate-tangle-sync-check
      (format nil "Org file not found: ~a" org-file)))
  (when (not (uiop:file-exists-p lisp-file))
    (return-from literate-tangle-sync-check
      (format nil "Lisp file not found: ~a" lisp-file)))
  (let* ((org-content (uiop:read-file-string org-file))
         (org-blocks (literate-extract-lisp-blocks org-content))
         (tangled (format nil "~{~a~^~%~%~}" org-blocks))
         (lisp-content (uiop:read-file-string lisp-file)))
    (if (string= (string-trim '(#\Space #\Newline) tangled)
                 (string-trim '(#\Space #\Newline) lisp-content))
        t
        (format nil "Tangle sync mismatch: ~a does not match ~a" org-file lisp-file))))

Skill Registration

(defskill :passepartout-programming-literate
  :priority 300
  :trigger (lambda (ctx) (declare (ignore ctx)) nil))