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,31 +0,0 @@
#+TITLE: PRD: Skill - Architect Agent
#+STATUS: FROZEN
#+AUTHOR: Agent
#+CREATED: [2026-03-31 Tue 12:15]
* 1. Purpose
Define the automated architectural behaviors for the PSF Consensus Loop. The Architect skill transforms a FROZEN PRD (Demand) into a rigorous PROTOCOL (Blueprint).
* 2. User Needs
** 2.1 PRD Perception
As the system orchestrator, I need the Architect to identify when a project is ready for blueprinting.
- The Architect MUST monitor `$PROJECTS_DIR` for `PRD.org` files with `#+STATUS: FROZEN`.
** 2.2 Semantic Translation
I need ambiguous requirements translated into executable interfaces.
- The Architect MUST generate `PROTOCOL.org` with Lisp-style function signatures for all core requirements.
- It MUST define the "Architectural Intent" to maintain long-term system integrity.
** 2.3 Institutional Memory Integration
I need architectural decisions to be grounded in experience.
- The Architect MUST reference `notes/institutional-memory.org` when making significant design choices.
** 2.4 Physical Actuation
I need the blueprint to be physically written to the project directory.
- The skill must have a symbolic (Lisp) actuator that writes the generated Org content to the disk.
* 3. Success Criteria
- [ ] **Trigger Accuracy:** Architect correctly identifies a `FROZEN` PRD and ignores `DRAFT` PRDs.
- [ ] **Protocol Generation:** Architect generates a `PROTOCOL.org` that contains at least one valid Lisp interface signature.
- [ ] **File Integrity:** The generated `PROTOCOL.org` is syntactically valid Org-mode and contains the correct front matter (`#+TITLE`, `#+STATUS: DRAFT`).

View File

@@ -1,40 +0,0 @@
#+TITLE: PROTOCOL: Skill - Architect Agent
#+STATUS: DRAFT
#+AUTHOR: Architect-Agent
#+CREATED: [2026-03-31 Tue 12:20]
* 1. Architectural Intent
This protocol defines the shared Lisp interfaces for the Architect skill. It ensures a rigorous "Consensus Loop" by defining how the Architect perceives requirements and actuates blueprints.
Following the **Literate Mandate**, the Architect skill's own implementation must be generated from its Org-mode source.
* 2. Semantic Interfaces
** 2.1 Requirements Perception
#+begin_src lisp
(defun architect-perceive-frozen-prd (project-name)
"Checks if a project has a FROZEN PRD.
Returns a plist: (:status :frozen :path \"path/to/PRD.org\") or NIL."
)
#+end_src
** 2.2 Blueprint Actuation
#+begin_src lisp
(defun architect-actuate-protocol (project-name blueprint-content)
"Physically writes the PROTOCOL.org file.
Input: project name and generated Org content.
Returns a success message or error signal."
)
#+end_src
** 2.3 Memory Retrieval
#+begin_src lisp
(defun architect-query-institutional-memory (context-tags)
"Retrieves relevant architectural patterns from notes/institutional-memory.org.
Input: tags like :emacs:gtd:psf.
Returns a list of relevant patterns/learnings."
)
#+end_src
* 3. Integration with PSF Lifecycle
The Architect is triggered when a project transitions from `:DEMAND` to `:BLUEPRINT`. Its output (a SIGNED Protocol) is the "Safety Gate" for the **Analyst** phase.

View File

@@ -0,0 +1,75 @@
;;;; architect-logic.lisp --- Architectural automation for the PSF (Unified).
;;;; This file is TANGLED from notes/org-skill-architect.org. DO NOT EDIT MANUALLY.
(defpackage :org-skill-architect
(:use :cl :uiop :local-time)
(:export #:architect-perceive-frozen-prd
#:architect-scan-all-notes
#:trigger-skill-architect
#:neuro-skill-architect
#:architect-actuate))
(in-package :org-skill-architect)
(defun kernel-log (message &rest args)
(format t "~&[ARCHITECT] ~?" message args))
(defun architect-perceive-frozen-prd (note-path)
"Checks if a master note has a FROZEN PRD and lacks a Phase B section."
(let ((content (uiop:read-file-string note-path)))
(when (and (search "* Phase A: Demand (PRD)" content)
(search ":STATUS: FROZEN" content)
(not (search "* Phase B: Blueprint (PROTOCOL)" content)))
`(:note-path ,note-path :content ,content))))
(defun architect-scan-all-notes ()
"Scans all org-skill-*.org notes for demands ready for blueprinting."
(let ((notes-dir (or (uiop:getenv "MEMEX_NOTES") "notes/"))
(ready-notes '()))
(dolist (file (uiop:directory-files notes-dir "org-skill-*.org"))
(let ((status (architect-perceive-frozen-prd file)))
(when status (push status ready-notes))))
ready-notes))
(defun trigger-skill-architect (context)
"Triggers on heartbeat if any master note is in a FROZEN PRD state."
(let ((type (getf context :type))
(payload (getf context :payload)))
(when (and (eq type :EVENT) (eq (getf payload :sensor) :heartbeat))
(let ((ready (architect-scan-all-notes)))
(when ready
(setf (getf (getf context :payload) :ready-notes) ready)
t)))))
(defun neuro-skill-architect (context)
(let* ((payload (getf context :payload))
(note (car (getf payload :ready-notes)))
(note-path (getf note :note-path))
(prd-content (getf note :content)))
(format nil "
You are the PSF Architect.
The Master Note '~a' has a FROZEN PRD and needs a PROTOCOL.
NOTE CONTENT:
---
~a
---
TASK:
Draft the '* Phase B: Blueprint (PROTOCOL)' section.
1. Define Architectural Intent.
2. Define Semantic Interfaces using Lisp signatures.
Return a Lisp plist: (:target :architect :action :actuate :path \"~a\" :content \"...blueprint section...\")
" note-path prd-content note-path)))
(defun architect-actuate (action context)
(let* ((payload (getf action :payload))
(note-path (getf payload :path))
(blueprint-content (getf payload :content)))
(kernel-log "Appending PROTOCOL to ~a" note-path)
(with-open-file (out note-path :direction :output :if-exists :append)
(format out "~%* Phase B: Blueprint (PROTOCOL)~%:PROPERTIES:~%:STATUS: SIGNED~%:END:~%~%~a"
blueprint-content))
(format nil "SUCCESS - Architect established PROTOCOL in ~a" note-path)))

View File

@@ -0,0 +1,47 @@
import os
import shutil
def simulate_perceive(project_name, projects_dir):
prd_path = os.path.join(projects_dir, project_name, "PRD.org")
protocol_path = os.path.join(projects_dir, project_name, "PROTOCOL.org")
if not os.path.exists(prd_path):
return None
with open(prd_path, 'r') as f:
content = f.read()
if "#+STATUS: FROZEN" in content and not os.path.exists(protocol_path):
return {"project": project_name, "prd_path": prd_path, "content": content}
return None
if __name__ == "__main__":
test_dir = "/tmp/architect_test_projects"
if os.path.exists(test_dir):
shutil.rmtree(test_dir)
os.makedirs(os.path.join(test_dir, "test-project"))
prd_file = os.path.join(test_dir, "test-project", "PRD.org")
print("--- Test 1: Draft PRD ---")
with open(prd_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: Frozen PRD ---")
with open(prd_file, "w") as f:
f.write("#+TITLE: Test\n#+STATUS: FROZEN\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: Protocol already exists ---")
with open(os.path.join(test_dir, "test-project", "PROTOCOL.org"), "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'}")

View File

@@ -1,47 +0,0 @@
#+TITLE: PRD: Org-Agent Memex (Knowledge Management Standards)
#+STATUS: FROZEN
#+AUTHOR: Agent
#+CREATED: [2026-03-31 Tue 11:45]
* 1. Purpose
Define the functional and technical requirements for an integrated Org-mode workflow that synchronizes Atomic Notes (Zettelkasten) and GTD task management. This PRD serves as the foundational specification for the "Memex Agent" skill.
* 2. User Needs
** 2.1 Unified Knowledge & Task Capture
As a user (Amr), I need a single entry point for all information.
- All new captures MUST land in `memex/inbox.org`.
- No other files are permitted for general inbox capture.
** 2.2 Strict Metadata Compliance
I need my PKM system to maintain high structural integrity.
- Every Org item must have a `:PROPERTIES:` drawer with a `:CREATED:` property in `[YYYY-MM-DD Day HH:MM]` format.
- Collaborative items must use `:AUTHOR:` and `:ASSIGNED:` properties.
- State changes MUST be tracked in a `:LOGBOOK:` drawer following the `:PROPERTIES:` drawer.
** 2.3 Automated Task Lifecycle
I need the agent to manage the "boring" parts of GTD.
- **Automatic NEXT Promotion:** When a `NEXT` item in a sequential project is marked `DONE`, the agent MUST automatically promote the subsequent `TODO` item to `NEXT`.
- **Agenda Coordination:** The agent must place items requiring my attention as `TODO` (planned) or `NEXT` (immediate) in my agenda.
** 2.4 Mobile Sovereignty
I need to interact with my Memex on the go.
- The system must remain compatible with Markor (for text editing) and Orgzly (for agenda management) on Android.
- Sync must be handled via a Git-based state machine (commits as source of truth).
** 2.5 Agentic Distillation (The Scribe)
I need my daily logs transformed into timeless knowledge.
- The agent must read from immutable daily logs (`daily/`).
- It must extract "Evergreen" concepts and write them to `notes/` as atomic notes.
- Atomic notes must have descriptive snake_case filenames (no dates) and a `Source:` backlink.
* 3. Success Criteria
- [ ] **Promotion Logic:** Agent successfully identifies a completed `NEXT` task and promotes its successor in a sequential project.
- [ ] **Metadata Audit:** Agent can identify and flag any Org item missing `:CREATED:` or `:LOGBOOK:` headers.
- [ ] **Scribe Accuracy:** Agent extracts a concept from a daily log and creates a correctly formatted atomic note in `notes/` without user intervention.
- [ ] **Git Synchronization:** All changes are automatically committed to the local repository for versioning and state tracking.
* 4. Constraints
- **Single User/Single Agent:** Designed exclusively for Amr and his Assistant. No multi-user conflict resolution.
- **Environment Driven:** All identity and path values must be pulled from `.env` (e.g., `$MEMEX_USER`, `$MEMEX_NOTES`).
- **Org-mode Native:** No external databases. The `.org` files ARE the database.

View File

@@ -1,57 +0,0 @@
#+TITLE: PROTOCOL: Org-Agent Memex (Knowledge Management Standards)
#+STATUS: SIGNED
#+AUTHOR: Architect-Agent
#+CREATED: [2026-03-31 Tue 12:00]
#+SIGNED: [2026-03-31 Tue 12:45] Agent (Architect)
* 1. Architectural Intent
This protocol defines the shared Lisp interfaces for the "Memex Agent" skill. Its goal is to automate the "boring" parts of the knowledge and task management lifecycle while maintaining strict structural integrity.
Following the **Single User/Single Agent** philosophy, all state transitions are event-driven and strictly reference the Org-mode AST as the primary data store. No external databases are permitted.
* 2. Semantic Interfaces
** 2.1 Metadata Integrity Audit
#+begin_src lisp
(defun memex-audit-metadata (file-path)
"Parses an Org file to ensure all entries comply with KM standards.
Checks for: :CREATED: property, :LOGBOOK: drawer placement, and :AUTHOR:/:ASSIGNED: for collaborative items.
Returns a plist of non-compliant entries: (:file \"path\" :errors (list-of-errors))"
)
(defun memex-fix-metadata (entry-id)
"Attempts to automatically fix missing headers (e.g., adding a missing :LOGBOOK: drawer or current timestamp to :CREATED:)."
)
#+end_src
** 2.2 GTD Task Promotion (The "Baton Pass")
#+begin_src lisp
(defun memex-promote-next-task (project-id)
"Triggered when a NEXT item in a sequential project is marked DONE.
1. Locates the project by ID in gtd.org.
2. Identifies the NEXT available TODO item in the sequence.
3. Promotes it to NEXT, updating the :LOGBOOK: state transition.
4. Returns the promoted task ID or NIL if no tasks remain."
)
#+end_src
** 2.3 Agentic Distillation (The Scribe Loop)
#+begin_src lisp
(defun memex-distill-atomic-note (daily-file-path concept-query)
"Extracts a specific concept from an immutable daily log and transforms it into a timeless atomic note.
1. Scans daily log for headers or tags matching the query.
2. Formats the note with concept-snake_case filename.
3. Adds a 'Source:' backlink to the original daily file.
4. Writes the result to $MEMEX_NOTES/.
Returns the path of the newly created note."
)
#+end_src
* 3. Integration with PARA and Git
The Memex Agent MUST perform a `git commit` after every successful task promotion or note distillation to ensure state persistence and provide a clear audit trail.
#+begin_src lisp
(defun memex-sync-state (commit-message)
"Stages and commits all changes to the local Git repository."
)
#+end_src

View File

@@ -1,34 +0,0 @@
#+TITLE: PRD: Skill - Project Foundry Agent
#+STATUS: FROZEN
#+AUTHOR: Agent
#+CREATED: [2026-03-31 Tue 14:15]
* 1. Purpose
Define the automated project instantiation behaviors for the PSF. The Project Foundry skill transforms a natural language project request (Demand) into a physically scaffolded, high-integrity project structure (Blueprint).
* 2. User Needs
** 2.1 Workspace Scaffolding
As a user (Amr), I need a consistent environment for every new project.
- The Foundry MUST create the standard PSF directory layout (`src/`, `tests/`, `docs/`).
- It MUST generate boilerplate literate files: `README.org`, `PRD.org`, and `PROTOCOL.org`.
** 2.2 Version Control Initialization
I need every project to be a Git repository from day one.
- The Foundry MUST run `git init` in the new project directory.
** 2.3 GTD Integration
I need new projects to be automatically tracked in my task management system.
- The Foundry MUST append the project and its initial tasks (`Draft PRD`, `Draft PROTOCOL`) to `gtd.org`.
- It MUST use `org-edna` or sibling-based triggers to maintain sequential integrity.
** 2.4 Idempotency and Safety
I need to prevent accidental data loss.
- The Foundry MUST NOT overwrite an existing project directory.
- It MUST log all physical actions to the kernel log.
* 3. Success Criteria
- [ ] **Structural Compliance:** Scaffolded project contains all required directories and files.
- [ ] **GTD Linkage:** New project appears in `gtd.org` with correct properties (`:PROJECT-PATH:`, `:PSF-STATE:`).
- [ ] **Literate Boilerplate:** Generated `PRD.org` and `PROTOCOL.org` contain the standard PSF templates.
- [ ] **Error Handling:** Foundry returns a clean error message if the project directory already exists.

View File

@@ -1,33 +0,0 @@
#+TITLE: PROTOCOL: Skill - Project Foundry Agent
#+STATUS: SIGNED
#+AUTHOR: Architect-Agent
#+CREATED: [2026-03-31 Tue 14:20]
* 1. Architectural Intent
This protocol defines the shared Lisp interfaces for the Project Foundry skill. It ensures that every project in the Memex is instantiated with high structural and semantic integrity.
* 2. Semantic Interfaces
** 2.1 Project Scaffolding
#+begin_src lisp
(defun scaffold-project (name type)
"Physically creates the PSF project structure on disk and links it to GTD."
)
#+end_src
** 2.2 Trigger Perception
#+begin_src lisp
(defun trigger-skill-project-foundry (context)
"Determines if the current context warrants a project instantiation."
)
#+end_src
** 2.3 Proposal Verification
#+begin_src lisp
(defun verify-skill-project-foundry (proposed-action context)
"Validates the Neuro-cognitive proposal before physical actuation."
)
#+end_src
* 3. Integration with GTD
The Foundry MUST append a new project entry to `gtd.org` using the standard PSF template, including `:PSF-STATE: A: DEMAND` and `:TRIGGER: next-sibling!`.

View File

@@ -0,0 +1,57 @@
;;;; foundry-logic.lisp --- Universal project scaffolding.
;;;; This file is TANGLED from notes/org-skill-project-foundry.org. DO NOT EDIT MANUALLY.
(defpackage :org-skill-project-foundry
(:use :cl :uiop :local-time)
(:export #:scaffold-project
#:trigger-skill-project-foundry
#:verify-skill-project-foundry))
(in-package :org-skill-project-foundry)
(defun kernel-log (message &rest args)
(format t "~&[FOUNDRY] ~?" message args))
(defun trigger-skill-project-foundry (context)
(let ((type (getf context :type))
(payload (getf context :payload)))
(and (eq type :EVENT)
(eq (getf payload :sensor) :delegation)
(eq (getf payload :target-skill) :foundry))))
(defun scaffold-project (name type)
"Physically creates the material PSF project and the Universal Literate Note."
(let* ((projects-dir (or (uiop:getenv "PROJECTS_DIR") "projects/"))
(notes-dir (or (uiop:getenv "MEMEX_NOTES") "notes/"))
(skills-dir (or (uiop:getenv "SKILLS_DIR") "system/skills/"))
(project-dir (format nil "~aorg-skill-~a/" projects-dir name))
(note-path (format nil "~aorg-skill-~a.org" notes-dir name))
(skill-link (format nil "~aorg-skill-~a.org" skills-dir name))
(gtd-file (or (uiop:getenv "GTD_FILE") "gtd.org"))
(timestamp (local-time:format-timestring nil (local-time:now) :format '("[" :year "-" :month "-" :day " " :weekday " " :hour ":" :min "]"))))
(if (or (uiop:directory-exists-p project-dir) (uiop:file-exists-p note-path))
(format nil "ERROR - Project or Note for ~a already exists." name)
(progn
(kernel-log "Scaffolding Universal PSF project: ~a" name)
(ensure-directories-exist (format nil "~asrc/" project-dir))
(ensure-directories-exist (format nil "~atests/" project-dir))
(ensure-directories-exist (format nil "~adocs/" project-dir))
(with-open-file (out note-path :direction :output :if-exists :supersede)
(format out "#+TITLE: SKILL: ~a (Universal Literate Note)~%#+ID: skill-~a~%#+STARTUP: content~%#+FILETAGS: :~a:psf:~%~%* Overview~%Automatically scaffolded ~a project.~%~%* Phase A: Demand (PRD)~%:PROPERTIES:~%:STATUS: DRAFT~%:END:~%~%** 1. Purpose~%Define the 'Why' and 'What' for ~a.~%"
name name type name name))
(uiop:run-program (list "ln" "-sf" note-path skill-link))
(with-open-file (out gtd-file :direction :output :if-exists :append)
(format out "~%** NEXT org-skill-~a~% :PROPERTIES:~% :ID: proj-~a~% :CREATED: ~a~% :PROJECT-PATH: ~a~% :PSF-STATE: A: DEMAND~% :END:~% Drafted by Project Foundry.~%"
name name timestamp project-dir))
(format nil "SUCCESS - Universal PSF Project ~a scaffolded." name)))))
(defun verify-skill-project-foundry (proposed-action context)
(let* ((payload (getf proposed-action :payload))
(action (getf proposed-action :action))
(name (getf payload :name))
(type (getf payload :type)))
(if (eq action :scaffold)
(let ((result (scaffold-project name type)))
`(:target :emacs :action :message :text ,result))
nil)))

View File

@@ -1,36 +0,0 @@
#+TITLE: PRD: Skill - Scribe Agent
#+STATUS: FROZEN
#+AUTHOR: Agent
#+CREATED: [2026-03-31 Tue 13:45]
* 1. Purpose
The Scribe Agent is the automated distillation and auditing engine for the PSF. Its primary goal is to prevent "context rot" by transforming daily captures into atomic notes and ensuring project compliance with PSF standards.
* 2. User Needs
** 2.1 Knowledge Distillation
As a user (Amr), I need my ephemeral daily thoughts transformed into a structured knowledge base.
- The Scribe MUST extract core concepts from `$MEMEX_DAILY`.
- It MUST generate normalized atomic notes in `$MEMEX_NOTES`.
- It MUST preserve provenance via `Source:` backlinks.
** 2.2 Incremental Processing
I need the system to be efficient and avoid redundant work.
- The Scribe MUST use Git state tracking (commit hashes) to identify only new content.
- It MUST maintain state in a Lisp-native format (`scribe-state.lisp`) for full system introspection.
** 2.3 PSF Mandate Audit
I need my foundry projects to maintain high integrity.
- The Scribe MUST audit active projects for `PRD.org`, `PROTOCOL.org`, and Literate Programming blocks.
- It MUST flag "Mandate Violations" in `institutional-memory.org`.
** 2.4 Autonomous Execution
I need the Scribe to run reliably without manual intervention.
- The skill must be compatible with cron-based triggers.
- It must handle path normalization via environment variables.
* 3. Success Criteria
- [ ] **Distillation Accuracy:** Scribe identifies a concept in a daily log and creates a correctly formatted atomic note.
- [ ] **Provenance Check:** Atomic notes contain a valid `Source:` link back to the daily file.
- [ ] **Audit Trigger:** Scribe correctly identifies a project missing a `PROTOCOL.org` and records the violation.
- [ ] **State Persistence:** `distillation-state.json` is updated after every successful run.

View File

@@ -1,48 +0,0 @@
#+TITLE: PROTOCOL: Skill - Scribe Agent
#+STATUS: SIGNED
#+AUTHOR: Architect-Agent
#+CREATED: [2026-03-31 Tue 13:50]
#+SIGNED: [2026-03-31 Tue 13:55] Agent (Architect)
* 1. Architectural Intent
This protocol defines the shared Lisp interfaces for the Scribe skill. It ensures that the distillation of ephemeral thoughts and the auditing of foundry integrity are performed deterministically and with clear provenance.
Following the **Literate Mandate**, the Scribe skill's implementation must be tangled from its Org-mode source.
* 2. Semantic Interfaces
** 2.1 State Perception
#+begin_src lisp
(defun scribe-scan-for-knowledge-gaps ()
"Uses 'git diff' against the last processed commit hash to identify new content in $MEMEX_DAILY.
Returns a list of daily files with new content."
)
#+end_src
** 2.2 Concept Distillation
#+begin_src lisp
(defun scribe-distill-concept (daily-path concept-meta)
"Transforms a raw capture into an atomic note.
Input: (:title \"Concept Title\" :content \"Body text\" :source \"daily/2026-03-31.org\")
Output: Path to the new note in $MEMEX_NOTES."
)
#+end_src
** 2.3 Mandate Auditing
#+begin_src lisp
(defun scribe-audit-foundry-mandate (project-name)
"Checks a project for compliance with PSF Level 3 standards.
Checks: PRD.org exists, PROTOCOL.org exists, src/ contains tangled blocks.
Returns a list of violations or NIL if compliant."
)
#+end_src
** 2.4 Integrity Reporting
#+begin_src lisp
(defun scribe-record-violation (project-name violation-type)
"Appends a Mandate Violation entry to notes/institutional-memory.org."
)
#+end_src
* 3. Integration with Cron and Git
The Scribe runs as an asynchronous process. It MUST update `scribe-state.lisp` (containing a Lisp alist) and perform a Git commit after each successful batch.

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'}")