feat(arch): finalize Universal Literate Note transition for all projects and skills

This commit is contained in:
2026-03-31 16:14:37 -04:00
parent 1712b1e4a9
commit 70be8ab93e
79 changed files with 1606 additions and 417 deletions

View File

@@ -1,33 +0,0 @@
#+TITLE: PRD: Skill - Technical Analyst Agent
#+STATUS: FROZEN
#+AUTHOR: Agent
#+CREATED: [2026-03-31 Tue 12:25]
* 1. Purpose
Define the automated testing and analysis behaviors for the PSF Consensus Loop. The Technical Analyst skill transforms a SIGNED PROTOCOL (Blueprint) into a comprehensive, failing TDD suite (Success Criteria).
* 2. User Needs
** 2.1 Protocol Perception
As the system orchestrator, I need the Analyst to identify when an architecture is ready for testing.
- The Analyst MUST monitor `$PROJECTS_DIR` for `PROTOCOL.org` files with `#+STATUS: SIGNED`.
** 2.2 TDD Inception (Success Criteria)
I need rigorous test cases generated from semantic interfaces.
- The Analyst MUST generate a test suite in the project's `tests/` directory.
- It MUST cover both the "Happy Path" and "Edge Case" scenarios.
- It MUST ensure that all tests match the function signatures defined in the project's `PROTOCOL.org`.
** 2.3 Automated Test Execution (Initial)
I need the Analyst to verify that the tests *fail* initially (Red-Green-Refactor).
- The skill must have a symbolic (Lisp) actuator that writes the generated test code and confirms its existence.
** 2.4 Structural Enforcement
I need the Analyst to ensure the project's `tests/` directory is correctly initialized.
- The Analyst MUST be able to scaffold the `tests/` directory if it is missing.
* 3. Success Criteria
- [ ] **Trigger Accuracy:** Analyst correctly identifies a `SIGNED` PROTOCOL and ignores `DRAFT` Protocols.
- [ ] **TDD Suite Generation:** Analyst generates a test suite that references at least one interface from the PROTOCOL.
- [ ] **Physical Inception:** The generated test code is physically written to `tests/test-suite.lisp` (or equivalent).
- [ ] **Edge Case Coverage:** The generated suite includes at least one negative test case (error handling).

View File

@@ -1,40 +0,0 @@
#+TITLE: PROTOCOL: Skill - Technical Analyst Agent
#+STATUS: DRAFT
#+AUTHOR: Tech-Analyst-Agent
#+CREATED: [2026-03-31 Tue 12:30]
* 1. Architectural Intent
This protocol defines the shared Lisp interfaces for the Technical Analyst skill. It ensures that the PSF Consensus Loop follows a strict TDD mandate by defining how the Analyst perceives signed architectures and actuates failing test suites.
Following the **Literate Mandate**, the Analyst skill's own implementation must be generated from its Org-mode source.
* 2. Semantic Interfaces
** 2.1 Blueprint Perception
#+begin_src lisp
(defun tech-analyst-perceive-signed-protocol (project-name)
"Checks if a project has a SIGNED PROTOCOL.
Returns a plist: (:status :signed :path \"path/to/PROTOCOL.org\") or NIL."
)
#+end_src
** 2.2 TDD Suite Actuation
#+begin_src lisp
(defun tech-analyst-actuate-tdd-suite (project-name test-content)
"Physically writes the TDD suite (test code) to the project.
Input: project name and generated Lisp/Python test code.
1. Ensures the 'tests/' directory exists.
2. Writes the content to 'tests/test-suite.*'.
Returns a success message or error signal."
)
#+end_src
** 2.3 Success Criteria Generation
#+begin_src lisp
(defun tech-analyst-generate-success-criteria (project-name)
"Extracts success criteria from the PROTOCOL and PRD to generate the 'RED' test suite."
)
#+end_src
* 3. Integration with PSF Lifecycle
The Analyst is triggered when a project transitions from `:BLUEPRINT` to `:SUCCESS`. Its output (a failing TDD suite in `tests/`) is the "Safety Gate" that permits the **Coder** (Phase D: Build) to begin implementation.

View File

@@ -0,0 +1,83 @@
;;;; analyst-logic.lisp --- TDD automation for the PSF (Unified).
;;;; This file is TANGLED from notes/org-skill-tech-analyst.org. DO NOT EDIT MANUALLY.
(defpackage :org-skill-tech-analyst
(:use :cl :uiop :local-time)
(:export #:tech-analyst-perceive-signed-protocol
#:tech-analyst-scan-all-notes
#:trigger-skill-tech-analyst
#:neuro-skill-tech-analyst
#:tech-analyst-actuate))
(in-package :org-skill-tech-analyst)
(defun kernel-log (message &rest args)
(format t "~&[ANALYST] ~?" message args))
(defun tech-analyst-perceive-signed-protocol (note-path)
"Checks if a master note has a SIGNED PROTOCOL and lacks a TDD suite in the material project."
(let* ((content (uiop:read-file-string note-path))
(filename (pathname-name note-path))
(project-name (subseq filename 10)) ; Extract 'name' from 'org-skill-name'
(projects-dir (or (uiop:getenv "PROJECTS_DIR") "projects/"))
(test-path (format nil "~aorg-skill-~a/tests/test-suite.lisp" projects-dir project-name)))
(when (and (search "* Phase B: Blueprint (PROTOCOL)" content)
(search ":STATUS: SIGNED" content)
(not (uiop:file-exists-p test-path)))
`(:project-name ,project-name :note-path ,note-path :content ,content))))
(defun tech-analyst-scan-all-notes ()
"Scans all org-skill-*.org notes for blueprints ready for testing."
(let ((notes-dir (or (uiop:getenv "MEMEX_NOTES") "notes/"))
(ready-notes '()))
(dolist (file (uiop:directory-files notes-dir "org-skill-*.org"))
(let ((status (tech-analyst-perceive-signed-protocol file)))
(when status (push status ready-notes))))
ready-notes))
(defun trigger-skill-tech-analyst (context)
"Triggers on heartbeat if any master note is in a SIGNED PROTOCOL state."
(let ((type (getf context :type))
(payload (getf context :payload)))
(when (and (eq type :EVENT) (eq (getf payload :sensor) :heartbeat))
(let ((ready (tech-analyst-scan-all-notes)))
(when ready
(setf (getf (getf context :payload) :ready-blueprints) ready)
t)))))
(defun neuro-skill-tech-analyst (context)
(let* ((payload (getf context :payload))
(note (car (getf payload :ready-blueprints)))
(name (getf note :project-name))
(protocol-content (getf note :content)))
(format nil "
You are the PSF Technical Analyst.
The Master Note for project '~a' has a SIGNED PROTOCOL and needs a TDD Suite.
PROTOCOL CONTENT:
---
~a
---
TASK:
Generate a comprehensive Common Lisp test suite (failing/RED).
1. Use FiveAM for testing.
2. Match function signatures exactly as defined in the PROTOCOL.
Return a Lisp plist: (:target :analyst :action :actuate :name \"~a\" :content \"...test code...\")
" name protocol-content name)))
(defun tech-analyst-actuate (action context)
(let* ((payload (getf action :payload))
(project-name (getf payload :name))
(test-content (getf payload :content))
(projects-dir (or (uiop:getenv "PROJECTS_DIR") "projects/"))
(project-dir (format nil "~aorg-skill-~a/" projects-dir project-name))
(test-dir (format nil "~atests/" project-dir))
(test-path (format nil "~atests/test-suite.lisp" project-dir)))
(kernel-log "Actuating TDD Suite for ~a" project-name)
(ensure-directories-exist test-dir)
(with-open-file (out test-path :direction :output :if-exists :supersede)
(format out ";;; TDD Suite for ~a~%~a" project-name test-content))
(format nil "SUCCESS - Technical Analyst established TDD Suite for ~a" project-name)))

View File

@@ -0,0 +1,47 @@
import os
import shutil
def simulate_perceive(project_name, projects_dir):
protocol_path = os.path.join(projects_dir, project_name, "PROTOCOL.org")
test_path = os.path.join(projects_dir, project_name, "tests", "test-suite.lisp")
if not os.path.exists(protocol_path):
return None
with open(protocol_path, 'r') as f:
content = f.read()
if "#+STATUS: SIGNED" in content and not os.path.exists(test_path):
return {"project": project_name, "protocol_path": protocol_path, "content": content}
return None
if __name__ == "__main__":
test_dir = "/tmp/analyst_test_projects"
if os.path.exists(test_dir):
shutil.rmtree(test_dir)
os.makedirs(os.path.join(test_dir, "test-project", "tests"))
proto_file = os.path.join(test_dir, "test-project", "PROTOCOL.org")
print("--- Test 1: Draft Protocol ---")
with open(proto_file, "w") as f:
f.write("#+TITLE: Test\n#+STATUS: DRAFT\n")
res = simulate_perceive("test-project", test_dir)
print(f"Result: {res}")
status1 = "PASS" if res is None else "FAIL"
print("\n--- Test 2: Signed Protocol ---")
with open(proto_file, "w") as f:
f.write("#+TITLE: Test\n#+STATUS: SIGNED\n")
res = simulate_perceive("test-project", test_dir)
print(f"Result: {res['project'] if res else None}")
status2 = "PASS" if res and res['project'] == "test-project" else "FAIL"
print("\n--- Test 3: TDD suite already exists ---")
with open(os.path.join(test_dir, "test-project", "tests", "test-suite.lisp"), "w") as f:
f.write("exists")
res = simulate_perceive("test-project", test_dir)
print(f"Result: {res}")
status3 = "PASS" if res is None else "FAIL"
print(f"\nFinal Status: {'PASS' if all(s == 'PASS' for s in [status1, status2, status3]) else 'FAIL'}")