#+TITLE: Root Cause Analysis: Asynchronous Lisp Repair Syntax Gate #+DATE: 2026-04-11 #+FILETAGS: :rca:lisp:repair:decoupling:architecture:psf: * Executive Summary Reimplemented the `org-skill-lisp-repair` to align with the "Sovereign Boundary" mandate. The previously synchronous, core-blocking repair logic has been replaced with an asynchronous, event-driven architecture using the Reactive Signal Pipeline. * 1. Issue: Core Bloat & Synchronous Coupling ** Symptoms The initial implementation of the Lisp Repair gate placed a `handler-case` and a dynamic function call (`repair-lisp-syntax`) directly inside the core `think` function (`neuro.lisp`). This forced the core to wait for repairs and made it "aware" of specific repair logic. ** Root Cause Architectural shortcutting. By placing repair logic in the core execution path, we violated the microkernel principle which mandates that the core should be a "dumb" signal processor. ** Resolution 1. **Refactored Core:** `think` now only emits a `:syntax-error` stimulus if parsing fails. It no longer attempts to repair. 2. **Asynchronous Skill:** `skill-lisp-repair` now triggers on the `:syntax-error` event. It performs the repair and returns the corrected action, which is then dispatched by the pipeline. * 2. Side-Issue: Nested Signal Payloads ** Symptoms `TYPE-ERROR` during testing when extracting the broken code from the stimulus. ** Root Cause Mismatched expectations of signal nesting. The skill expected the code at `(getf context :payload)`, but in the `decide-gate`, `context` is the full signal, and the error details were nested inside the `:candidate` field of that signal. ** Resolution Updated the symbolic logic to correctly traverse the nested signal structure: `(getf (getf context :candidate) :payload)`. * 3. PSF Mandate Alignment ** Sovereign Boundary The core is now strictly a parser. Repair is an optional, user-space service. ** Reactive Signal Pipeline Leveraged the pipeline's ability to re-inject `EVENT` signals to flatten the recursion of the repair loop. * 4. Permanent Learnings - **Emit, Don't Call:** In a microkernel, if a non-fatal error occurs, always emit a signal rather than calling a recovery function. This allows the system to remain asynchronous and modular. - **Signal Inspection:** When writing symbolic gates, always verify the exact shape of the `context` signal being passed by the kernel to avoid nesting errors.