docs: Comprehensive documentation for core skills and README
Some checks failed
Deploy-Agent-V15-Stdin / JOB-V15-STDIN (push) Failing after 3s

- Policy skill: Add philosophical foundation, invariant priority explanations, code block documentation
- Bouncer skill: Add security vector explanations, flight plan workflow, approval lifecycle
- README: Add architecture diagrams (mermaid), design principles, roadmap details

Each function now has detailed docstrings explaining:
- What it does
- Why it was designed that way
- How it fits into the larger system
This commit is contained in:
2026-04-22 16:58:10 -04:00
parent 2cdd8fe1a4
commit 1f10e51309
3 changed files with 940 additions and 236 deletions

View File

@@ -1,7 +1,7 @@
:PROPERTIES:
:ID: bouncer-agent-skill
:CREATED: [2026-04-11 Sat 15:20]
:EDITED: [2026-04-13 Mon 18:35]
:EDITED: [2026-04-22 Wed 16:00]
:END:
#+DEPENDS_ON: org-skill-credentials-vault
#+TITLE: SKILL: Deterministic Engine Bouncer (Authorization Gate)
@@ -9,149 +9,373 @@
#+FILETAGS: :system:bouncer:authorization:autonomy:
* Overview
The *Deterministic Engine Bouncer* is the authorization gate for high-risk actions. It serializes intercepted actions into Org nodes ("Flight Plans") and re-injects them once manually approved by the Autonomous.
The *Bouncer Skill* is the physical security layer of OpenCortex. While the Policy skill enforces constitutional invariants (transparency, autonomy, modularity), the Bouncer enforces operational security checks.
Think of Policy as the constitution and Bouncer as the bouncer at the door:
- **Policy** asks: "Is this action aligned with our values?"
- **Bouncer** asks: "Is this action safe to execute?"
** The Flight Plan Pattern
High-risk actions don't simply pass or fail—they can enter the "Flight Plan" approval workflow:
1. Bouncer intercepts a risky action
2. Creates an Org node ("Flight Plan") describing the action
3. User manually approves the flight plan in Emacs
4. Bouncer detects approval on next heartbeat
5. Action is re-injected with `approved = t` flag, bypassing the gate
This creates human-in-the-loop oversight for dangerous operations without blocking the system entirely.
** Why a Separate Skill?**
Security and policy are separated for clarity and auditability:
- Policy decisions can be explained (they reference invariants)
- Bouncer decisions are technical (they reference threat vectors)
When something is blocked, the logs clearly show which layer blocked it and why.
* Package Context
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(in-package :opencortex)
#+end_src
* Deep Packet Inspection (DPI)
The Bouncer ensures the action is "safe" by inspecting the payload content via Deep Packet Inspection.
* Security Vectors
** Secret Exposure Check
Retrieves all active secrets from the vault and scans the payload for potential leaks.
The Bouncer implements the 5-Vector security model:
| Vector | Threat | Response |
|--------|--------|----------|
| Secret Exposure | API keys, passwords in output | Hard block |
| Network Exfiltration | Data sent to unauthorized hosts | Approval required |
| Shell Execution | Arbitrary command execution | Approval required |
| File Modification | Writing/deleting files | Soft check |
| Eval Execution | Arbitrary code evaluation | Approval required |
** Secret Exposure Detection
The vault stores sensitive credentials. This check scans action text for vault secrets to prevent accidental exposure.
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(defun bouncer-scan-secrets (text)
"Returns the name of the secret found in TEXT, or NIL if clean."
"Scans TEXT for known secrets from the vault.
RETURNS: The name of the matched secret, or NIL if text is clean.
This prevents the catastrophic failure mode where the agent
accidentally echoes an API key in its response or log output.
The check uses substring matching (not regex) for reliability.
Only secrets longer than 5 characters are checked to avoid
false positives on common words."
(when (and text (stringp text))
(let ((found-secret nil))
(maphash (lambda (key val)
;; Only check secrets of meaningful length
(when (and val (stringp val) (> (length val) 5))
;; Search for secret value in action text
(when (search val text)
(setf found-secret key))))
opencortex::*vault-memory*)
found-secret)))
#+end_src
** Network Exfiltration Check
Inspects shell commands for unwhitelisted domains or IP addresses.
** Network Exfiltration Detection
Detects when shell commands try to send data to untrusted network destinations.
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(defvar *bouncer-network-whitelist*
'("api.telegram.org" "matrix.org" "googleapis.com" "openai.com" "anthropic.com")
"Domains that the Bouncer considers safe for outbound connections.
This whitelist should be minimal—only services explicitly configured
as gateways. All other outbound connections require approval.")
(defun bouncer-check-network-exfil (cmd)
"Returns T if the command appears to target an unwhitelisted external host."
"Detects if CMD attempts to contact an unwhitelisted external host.
Returns T if the command targets an unknown external host.
Returns NIL if the command is clean or only contacts whitelisted hosts.
The check looks for HTTP/HTTPS/FTP URLs and extracts the domain.
If the domain isn't in *bouncer-network-whitelist*, it's flagged."
(when (and cmd (stringp cmd))
;; Basic check for common data exfiltration tools being used with IPs/URLs
(let ((network-whitelist '("api.telegram.org" "matrix.org" "googleapis.com" "openai.com" "anthropic.com")))
(when (cl-ppcre:scan "(http|https|ftp)://([\\w\\.-]+)" cmd)
(multiple-value-bind (match regs)
(cl-ppcre:scan-to-strings "(http|https|ftp)://([\\w\\.-]+)" cmd)
(declare (ignore match))
(let ((domain (aref regs 1)))
(not (some (lambda (safe) (search safe domain)) network-whitelist))))))))
;; Look for URL patterns in the command
(when (cl-ppcre:scan "(http|https|ftp)://([\\w\\.-]+)" cmd)
(multiple-value-bind (match regs)
(cl-ppcre:scan-to-strings "(http|https|ftp)://([\\w\\.-]+)" cmd)
(declare (ignore match))
(let ((domain (aref regs 1)))
;; Check if domain is whitelisted
(not (some (lambda (safe) (search safe domain))
*bouncer-network-whitelist*)))))))
#+end_src
* Runtime Guard (bouncer-check)
The primary entry point for all high-impact actions. It blocks or queues actions based on risk vectors.
* Runtime Guard
** bouncer-check: Main Security Gate
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(defun bouncer-check (action context)
"The 5-Vector security gate. Blocks or queues actions based on risk."
"The 5-Vector security gate for high-risk actions.
Evaluates an action against all security vectors and either:
- Returns the action unchanged (pass)
- Returns a blocking LOG event (hard block)
- Returns an approval-required EVENT (soft block)
Vector evaluation order:
1. Already approved actions pass immediately
2. Secret exposure → hard block
3. Network exfiltration → approval required
4. High-impact targets → approval required
The context parameter is not used directly but provided for
consistency with the skill gate signature."
(declare (ignore context))
(let* ((target (getf action :target))
(payload (getf action :payload))
(text (or (getf payload :text) (getf action :text)))
;; Extract cmd from direct shell or tool-mediated shell call
(cmd (or (getf payload :cmd)
(when (and (eq target :tool) (equal (getf payload :tool) "shell"))
(getf (getf payload :args) :cmd))))
(when (and (eq target :tool)
(equal (getf payload :tool) "shell"))
(getf (getf payload :args) :cmd))))
(approved (getf action :approved)))
(cond
;; 0. Bypass for already approved actions
(approved action)
;; 1. Secret Exposure Vector (Hard Block)
(cond
;; Vector 0: Already approved actions pass through
(approved
action)
;; Vector 1: Secret Exposure (Hard Block)
;; If any vault secret is found in the action text, block immediately
((and text (bouncer-scan-secrets text))
(let ((secret-name (bouncer-scan-secrets text)))
(harness-log "SECURITY VIOLATION: Blocked leak of secret ~a" secret-name)
`(:type :log :payload (:level :error :text ,(format nil "Action blocked: Potential exposure of ~a" secret-name)))))
(harness-log "SECURITY VIOLATION: Blocked potential leak of secret '~a'" secret-name)
(list :type :LOG
:payload (list :level :error
:text (format nil "Action blocked: Potential exposure of '~a'" secret-name)))))
;; 2. Network Exfiltration Vector (Authorization Required)
((and (or (eq target :shell)
(and (eq target :tool) (equal (getf payload :tool) "shell")))
;; Vector 2: Network Exfiltration (Soft Block)
;; Shell commands targeting unknown hosts require approval
((and (or (eq target :shell)
(and (eq target :tool)
(equal (getf payload :tool) "shell")))
(bouncer-check-network-exfil cmd))
(harness-log "SECURITY WARNING: External network call detected. Queuing for approval.")
`(:type :EVENT :payload (:sensor :approval-required :action ,action)))
;; 3. High-Impact Target Vector (Authorization Required)
(list :type :EVENT
:payload (list :sensor :approval-required
:action action)))
;; Vector 3: High-Impact Targets (Soft Block)
;; Shell execution, file repair, and eval require approval
((or (member target '(:shell))
(and (eq target :tool) (member (getf payload :tool) '("shell" "repair-file") :test #'string=))
(and (eq target :EMACS) (eq (getf payload :action) :eval)))
(harness-log "SECURITY: High-impact action ~a requires approval." (or (getf payload :tool) target))
`(:type :EVENT :payload (:sensor :approval-required :action ,action)))
(and (eq target :tool)
(member (getf payload :tool) '("shell" "repair-file") :test #'string=))
(and (eq target :emacs)
(eq (getf payload :action) :eval)))
;; 4. Default Pass
(t action))))
(harness-log "SECURITY: High-impact action requires approval: ~a"
(or (getf payload :tool) target))
(list :type :EVENT
:payload (list :sensor :approval-required
:action action)))
;; Vector 4: Default pass
(t
action))))
#+end_src
* Approval Processing
The Bouncer periodically scans the Memex for approved "Flight Plans" and re-injects them into the metabolic loop.
* Flight Plan Workflow
** Processing Approvals
When a flight plan is approved in Emacs, the Bouncer detects it and re-injects the action.
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(defun bouncer-process-approvals ()
"Scans the object store for APPROVED flight plans and re-injects their actions."
"Scans the object store for APPROVED flight plans and re-injects them.
This function is called on every heartbeat, allowing the agent to
check for approvals without blocking the main signal pipeline.
Flight Plan format:
- Has TAGS including \"FLIGHT_PLAN\"
- Has TODO set to \"APPROVED\"
- Has ACTION containing the serialized action plist
When an approved flight plan is found:
1. Deserialize the action from the ACTION attribute
2. Mark the action as :approved = t (bypasses security gate)
3. Re-inject into the signal pipeline
4. Mark the flight plan as DONE
Returns T if any flight plans were processed."
(let ((approved-nodes (list-objects-with-attribute :TODO "APPROVED"))
(found-any nil))
(dolist (node approved-nodes)
(let* ((tags (getf (org-object-attributes node) :TAGS))
(action-str (getf (org-object-attributes node) :ACTION)))
(when (and (member "FLIGHT_PLAN" tags :test #'string-equal) action-str)
(harness-log "BOUNCER: Found approved flight plan ~a. Re-injecting..." (org-object-id node))
;; Only process flight plans (not other APPROVED items)
(when (and (member "FLIGHT_PLAN" tags :test #'string-equal)
action-str)
(harness-log "BOUNCER: Found approved flight plan '~a'. Re-injecting..."
(org-object-id node))
(let ((action (ignore-errors (read-from-string action-str))))
(when action
;; Mark as approved to bypass the gate
;; Mark as approved to bypass the security gate on re-injection
(setf (getf action :approved) t)
;; Re-inject the action into the signal pipeline
(inject-stimulus action)
;; Mark as DONE
;; Mark the flight plan as done
(setf (getf (org-object-attributes node) :TODO) "DONE")
(setq found-any t))))))
found-any))
#+end_src
* Skill Definition
The Bouncer skill reacts to approval requirements by creating flight plan nodes, and periodically checks for manual approvals via heartbeats.
** Creating Flight Plans
When the Bouncer intercepts a high-risk action, it creates a flight plan node for manual approval.
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(defun bouncer-create-flight-plan (blocked-action)
"Creates an Org node representing a pending flight plan for manual approval.
BLOCKED-ACTION is the action plist that was intercepted.
The flight plan node contains:
- A title describing the action
- TODO set to PLAN (awaiting approval)
- TAGS including FLIGHT_PLAN
- ACTION attribute containing the serialized action
The user reviews the flight plan and changes TODO to APPROVED.
On the next heartbeat, bouncer-process-approvals will detect
the approval and re-inject the action.
Returns the generated org-id for the flight plan."
(let ((id (org-id-new)))
(harness-log "BOUNCER: Creating flight plan node '~a'..." id)
;; Inject a node creation request
(list :type :REQUEST
:target :emacs
:payload (list :action :insert-node
:id id
:attributes (list
:TITLE "Flight Plan: High-Risk Action"
:TODO "PLAN"
:TAGS '("FLIGHT_PLAN")
:ACTION (format nil "~s" blocked-action)))))
#+end_src
* Skill Gate
** Main Gate Function
** Skill Logic
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(defun bouncer-deterministic-gate (action context)
"Main gate for the bouncer skill."
"Main deterministic gate for the Bouncer skill.
Handles three types of signals:
1. :approval-required - Create a flight plan for the blocked action
2. :heartbeat - Process any pending approvals
3. otherwise - Run security check on the action
The trigger is always true (bouncer evaluates all actions)
because security cannot be selective."
(let* ((payload (getf context :payload))
(sensor (getf payload :sensor)))
(case sensor
;; Signal type 1: Action was blocked, create flight plan
(:approval-required
(let* ((blocked-action (getf payload :action))
(id (org-id-new)))
(harness-log "BOUNCER: Creating flight plan node...")
;; Create the node in Emacs (or inbox)
(list :type :REQUEST :target :EMACS :action :insert-node
:id id :attributes `(:TITLE "Flight Plan: High-Risk Action"
:TODO "PLAN"
:TAGS ("FLIGHT_PLAN")
:ACTION ,(format nil "~s" blocked-action)))))
(let* ((blocked-action (getf payload :action)))
(bouncer-create-flight-plan blocked-action)))
;; Signal type 2: Heartbeat, check for approvals
(:heartbeat
;; Periodically check for approvals
(bouncer-process-approvals)
(if action (bouncer-check action context) action))
;; After processing approvals, still run the security check
(if action
(bouncer-check action context)
action))
;; Signal type 3: Normal action, run security check
(otherwise
(if action (bouncer-check action context) action)))))
(if action
(bouncer-check action context)
action)))))
#+end_src
** Skill Registration
#+begin_src lisp :tangle ../library/gen/org-skill-bouncer.lisp
(defskill :skill-bouncer
:priority 150
:trigger (lambda (ctx) t) ;; Bouncer evaluates all actions deterministically
:trigger (lambda (ctx) (declare (ignore ctx)) t)
:probabilistic nil
:deterministic #'bouncer-deterministic-gate)
#+end_src
* Quick Reference
** Security Vectors Summary
| Vector | Check | Response |
|--------|-------|----------|
| Secret Exposure | `bouncer-scan-secrets` | Hard block |
| Network Exfil | `bouncer-check-network-exfil` | Approval required |
| Shell Execution | target = :shell or tool = "shell" | Approval required |
| Eval Execution | target = :emacs and action = :eval | Approval required |
| File Repair | tool = "repair-file" | Approval required |
** Flight Plan Lifecycle
1. High-risk action intercepted → `:approval-required` signal
2. Flight plan node created in Emacs with `TODO: PLAN`
3. User reviews and sets `TODO: APPROVED`
4. Next heartbeat detects approval
5. Action re-injected with `approved = t`
6. Security gate bypassed, action executes
7. Flight plan marked `TODO: DONE`
* See Also
- [[file:org-skill-credentials-vault.org][Credentials Vault]] - Where secrets are stored
- [[file:org-skill-policy.org][Policy Skill]] - Constitutional constraints
- [[file:../harness/act.org][Act Stage]] - Where gates are invoked

View File

@@ -1,33 +1,65 @@
:PROPERTIES:
:ID: 47425a43-2be0-423c-8509-22592cfe9c9e
:CREATED: [2026-04-07 Tue 12:57]
:EDITED: [2026-04-22 Wed 11:45]
:EDITED: [2026-04-22 Wed 16:00]
:END:
#+TITLE: SKILL: System Policy
#+STARTUP: content
#+FILETAGS: :platform:policy:alignment:autonomy:
* Overview
The *opencortex* is a probabilistic-deterministic harness for a personal operating system. It uses Org-mode as its native memory and Common Lisp as its deterministic reasoning engine.
This skill defines the *Core System Policy*: a set of non-negotiable philosophical and technical constraints that every agentic action MUST satisfy. Unlike a passive manifesto, these invariants are enforced by the Deterministic Engine at the last mile before actuation.
The *Policy Skill* is the constitutional law of OpenCortex. It defines the non-negotiable constraints that every agentic action must satisfy before reaching the actuator layer.
Unlike a passive manifesto, Policy is *enforced* by the Deterministic Engine. The LLM proposes; Policy verifies. If an action violates an invariant, Policy blocks it and returns an auditable explanation.
** Why a Constitutional Approach?**
AIs fail in two ways:
1. *Underconstraint* - They do harmful things because no one told them not to
2. *Overconstraint* - They refuse to act because every action triggers a warning
OpenCortex solves this with a *hierarchy of invariants*:
- Some invariants block absolutely (Transparency, Modularity)
- Others warn but don't block (Autonomy debt, Sustainability debt)
This allows the agent to be both *safe* and *usable*.
** The Philosophical Foundation
OpenCortex is not just software—it's a *personal operating system* designed for the 100-year horizon. The Memex must outlive:
- Cloud services that get discontinued
- Programming languages that fall out of fashion
- Hardware platforms that become obsolete
Therefore, Policy encodes not just rules, but *values*:
- Radical Transparency → Auditability is non-negotiable
- Autonomy → Dependency on proprietary systems is debt, not strength
- Zero-Bloat → Complexity is cost, not feature
- Modularity → The kernel must survive even if all skills fail
- Mentorship → Teaching is the highest form of assistance
- Sustainability → Offline capability is a feature, not a limitation
* Package Context
Every skill executes within its own jailed package namespace, while inheriting core harness symbols.
Every skill executes within its own jailed package namespace, inheriting core harness symbols while maintaining isolation from other skills.
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(in-package :opencortex)
#+end_src
* The Override Hierarchy
When two invariants conflict, resolution follows a strict priority order. This prevents the agent from freezing on ethical edge cases.
1. *Radical Transparency* — An action that cannot be explained to the user is never permissible, even if it is technically optimal.
2. *Autonomy* — Independence from proprietary control is the primary goal, but it must be achieved transparently.
3. *Zero-Bloat* — Complexity must be justified, but a transparent, autonomous system may still be complex if the complexity is locally justified.
4. *Modularity* — The system's kernel must remain minimal; complexity must live at the edges, not in the core. This takes precedence over mentorship when the proposed change would fatten the harness.
5. *Mentorship* — The agent must teach, but teaching is secondary to delivering a working, transparent system.
6. *Long-Term Sustainability* — Energy efficiency and offline capability are desired properties, not absolute blockers.
| Priority | Invariant | Philosophy |
|----------|-----------|------------|
| 500 | Transparency | If you can't explain it, you can't do it |
| 400 | Autonomy | Independence from proprietary control is the primary goal |
| 300 | Zero-Bloat | Complexity must be earned, not imported |
| 250 | Modularity | Complexity belongs at the edges, not the core |
| 200 | Mentorship | Teaching increases capability; doing removes it |
| 100 | Sustainability | Offline capability today enables 100-year survival |
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *policy-invariant-priorities*
@@ -38,29 +70,55 @@ When two invariants conflict, resolution follows a strict priority order. This p
(:mentorship . 200)
(:sustainability . 100))
"Priority alist for policy invariant conflict resolution.
Higher numbers take precedence.")
Higher numbers take precedence.
When two invariants conflict, the higher priority wins.
Example: Modularity (250) takes precedence over Mentorship (200),
meaning a change that would fatten the harness is blocked
even if it would be educational.")
#+end_src
* The Core Invariants
** 1. Radical Transparency
The agent's "Thought Stream" must be fully auditable. Hidden reasoning or obfuscated logic is a violation of the system's design principles. At the action gate, this means every action directed at the user MUST carry an explanation, and every action MUST be a valid, inspectable data structure.
*The maxim: "If you can't explain it, you can't do it."*
The agent's Thought Stream must be fully auditable. Hidden reasoning or obfuscated logic violates the system's core purpose: a transparent, comprehensible AI assistant.
At the gate:
- Every action must be a valid, inspectable data structure
- Every user-facing action must carry an `:explanation`
- Log messages must include the triggering invariant
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defun policy-check-transparency (action context)
"Ensures the action is inspectable and user-facing actions carry an explanation.
Returns the action if clean, or a blocking LOG event if the action is opaque."
TRANSPARENCY CHECK:
1. Action must be a valid plist (not opaque data)
2. User-facing actions (:cli, :tui, :emacs) must include :explanation
3. Heartbeat and handshake messages are exempt (they're system status)
Returns the action if clean, or a blocking LOG event if violated."
(declare (ignore context))
;; Check 1: Action must be a valid plist
(unless (listp action)
(return-from policy-check-transparency
(list :type :LOG
:payload (list :level :error
:text "POLICY [Transparency]: Action is not a valid plist. Rejected."))))
(let* ((payload (getf action :payload))
(target (or (getf action :target) (getf action :TARGET)))
(explanation (or (getf payload :explanation) (getf payload :EXPLANATION)
(getf payload :rationale) (getf payload :RATIONALE))))
;; User-facing actions (CLI, TUI, Emacs) must explain themselves
(explanation (or (getf payload :explanation)
(getf payload :EXPLANATION)
(getf payload :rationale)
(getf payload :RATIONALE))))
;; Check 2: User-facing actions require explanation
(when (and (member target '(:cli :tui :emacs :EMACS :CLI :TUI))
(not explanation)
(not (member (getf payload :action)
@@ -68,235 +126,427 @@ Returns the action if clean, or a blocking LOG event if the action is opaque."
(return-from policy-check-transparency
(list :type :LOG
:payload (list :level :error
:text "POLICY [Transparency]: User-facing action missing :explanation. Blocked."))))
action))
:text "POLICY [Transparency]: User-facing action missing :explanation. Blocked.")))))
action)
#+end_src
** 2. Autonomy Above All
Every action must increase the user's independence from centralized, proprietary platforms. If a tool or library introduces a dependency on a non-autonomous entity, it must be flagged for replacement. The gate scans shell commands and tool payloads for known proprietary domains and logs a warning. It does NOT block by default, because the system itself uses gateway bridges (e.g., Telegram, Signal) as tactical concessions toward strategic autonomy.
*The maxim: "Every dependency is debt."*
Every action should increase the user's independence from centralized, proprietary platforms. When the system uses a proprietary API, it's logged as "autonomy debt"—acceptable tactically, but flagged for eventual replacement.
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *proprietary-domain-watchlist*
'("googleapis.com" "api.openai.com" "anthropic.com" "api.groq.com" "openrouter.ai")
"Domains that represent centralized, proprietary control.
Actions targeting these are logged as autonomy debt, not hard-blocked,
because tactical gateway usage is permitted under the strategic mandate.")
"Domains representing centralized, proprietary control.
Actions targeting these are logged as autonomy debt, not hard-blocked.
This is because tactical gateway usage (Telegram, Signal, OpenRouter)
is permitted under the strategic mandate for autonomy.
Strategic goal: Replace all proprietary APIs with local alternatives.
Tactical reality: Use what's available while building toward that goal.")
(defun policy-scan-proprietary-references (action)
"Scans ACTION text fields for proprietary domain references.
Returns the first matched domain, or NIL if clean."
Searches in:
- :text and :TEXT in payload
- :cmd and :CMD in payload
- :cmd in args (for shell tool calls)
Returns the first matched domain, or NIL if clean."
(let* ((payload (getf action :payload))
(text (or (getf payload :text) (getf payload :TEXT) ""))
(cmd (or (getf payload :cmd) (getf payload :CMD)
(when (equal (getf payload :tool) "shell")
(getf (getf payload :args) :cmd))
""))
(cmd (or (getf payload :cmd)
(getf payload :CMD)
(when (equal (getf payload :tool) "shell")
(getf (getf payload :args) :cmd))
""))
(haystack (concatenate 'string text cmd)))
(dolist (domain *proprietary-domain-watchlist* nil)
(when (search domain haystack)
(return domain)))))
(defun policy-check-autonomy (action context)
"Flags actions that reference proprietary domains. Returns the action
with an autonomy debt log appended, or the action itself if clean."
"Flags actions that reference proprietary domains.
Does NOT block the action—this is a warning, not a veto.
The agent can use proprietary services tactically, but must
be aware that each usage is a step away from full autonomy.
Returns a warning LOG if proprietary reference detected,
or the original action if clean."
(declare (ignore context))
(let ((domain (policy-scan-proprietary-references action)))
(if domain
(progn
(harness-log "POLICY [Autonomy]: Detected proprietary reference '~a'. Flagged for replacement." domain)
;; Return a side-effect log but DO NOT block the action
;; Return a warning log but DO NOT block the action
(list :type :LOG
:payload (list :level :warn
:text (format nil "Autonomy Debt: Action references proprietary domain '~a'. Consider a local alternative." domain)
:original-action action)))
action)))
action))
#+end_src
** 3. Zero-Bloat Mandate
The system harness must remain minimalist. "Just-in-case" code is a security vulnerability. Complexity must be earned, not imported. This invariant is enforced primarily at skill-load time (see `validate-lisp-syntax` and skill telemetry). At the action gate, it performs a lightweight size check on proposed `:create-skill` actions and warns if the payload exceeds a reasonable threshold.
*The maxim: "Complexity is cost, not feature."*
The system harness must remain minimalist. "Just-in-case" code is a security vulnerability. Complexity must be earned through demonstrated need, not anticipation of future use.
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *policy-max-skill-size-chars* 50000
"Maximum recommended size for a skill file tangled from an Org note.")
"Maximum recommended size for a skill file tangled from an Org note.
This is a soft limit—the check warns but does not block.
A large, well-documented skill is acceptable; a small, poorly-documented
one that adds unnecessary complexity is not.")
(defun policy-check-bloat (action context)
"Warns if a :create-skill action exceeds the bloat threshold.
Does not block, because size alone is not a proof of complexity."
Size alone is not proof of complexity—a 50KB skill that's well-designed
is better than a 5KB skill that's spaghetti. This check flags for review,
not automatic rejection.
Returns a warning LOG if threshold exceeded, or original action if clean."
(declare (ignore context))
(let* ((payload (getf action :payload))
(act (getf payload :action))
(content (getf payload :content)))
(when (and (eq act :create-skill)
(stringp content)
(> (length content) *policy-max-skill-size-chars*))
(harness-log "POLICY [Bloat]: Proposed skill is ~a chars. Exceeds ~a char threshold."
(length content) *policy-max-skill-size-chars*)
(return-from policy-check-bloat
(list :type :LOG
:payload (list :level :warn
:text (format nil "Bloat Warning: Proposed skill (~a chars) exceeds ~a char threshold. Review for earned complexity."
(length content) *policy-max-skill-size-chars*)
(length content) *policy-max-skill-size-chars*)
:original-action action))))
action))
action)
#+end_src
** 4. Technical Mastery & Mentorship
The agent's goal is not to "do it for the user," but to "empower the user." Every autonomous action must be explained at a level that increases the user's technical understanding of the Lisp Machine. At the gate, this means that any action which performs a non-trivial side-effect (file write, shell execution, skill reload) MUST include a `:mentorship-note` explaining *what* was done and *why*.
** 4. Modularity
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *mentorship-required-actions*
'(:create-skill :eval :modify-file :write-file :replace :rename-file :delete-file :shell :create-note)
"Actions that trigger the Mentorship invariant.")
*The maxim: "The kernel must survive even if all skills fail."*
(defun policy-check-mentorship (action context)
"Blocks high-impact actions that lack a mentorship note."
(declare (ignore context))
(let* ((payload (getf action :payload))
(act (or (getf payload :action) (getf action :action)))
(note (or (getf payload :mentorship-note) (getf payload :MENTORSHIP-NOTE)))
(target (or (getf action :target) (getf action :TARGET)))
(tool (when (eq target :tool) (getf payload :tool))))
(when (or (member act *mentorship-required-actions*)
(member tool '("shell" "eval" "repair-file")))
(unless note
(return-from policy-check-mentorship
(list :type :LOG
:payload (list :level :error
:text "POLICY [Mentorship]: High-impact action missing :mentorship-note. Explain what you are doing and why. Blocked.")))))
action))
#+end_src
Every system should be decomposed into a minimal, unbreakable core and hot-swappable capabilities. Complexity must live at the edges, never in the kernel.
** 5. Long-Term Sustainability
Prioritize local, energy-efficient, and offline-first architectures. The "Memex" should be functional on a 100-year horizon. At the gate, this means we log a sustainability debt event whenever the probabilistic engine falls back to a remote cloud provider because a local model (e.g., Ollama) is unavailable.
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *cloud-only-backends* '(:openrouter :openai :anthropic :groq :gemini-api)
"Backends that require an internet connection and external infrastructure.")
(defun policy-check-sustainability (action context)
"Logs sustainability debt when the action relies on cloud-only infrastructure.
Does not block, because tactical cloud usage is permitted."
(let* ((payload (getf context :payload))
(backend (getf payload :backend))
(provider (getf payload :provider)))
(when (or (member backend *cloud-only-backends*)
(member provider *cloud-only-backends*))
(harness-log "POLICY [Sustainability]: Cloud provider '~a' used. Logged as sustainability debt."
(or backend provider))
(return-from policy-check-sustainability
(list :type :LOG
:payload (list :level :warn
:text (format nil "Sustainability Debt: Reliance on cloud provider '~a'. Consider Ollama or local inference."
(or backend provider))))))
action))
#+end_src
** 6. Modularity
Every system should be decomposed into a minimal, unbreakable core and hot-swappable capabilities. Complexity must live at the edges, never in the kernel. At the gate, this means any proposed modification to the protected core must carry a `:modularity-justification` explaining why the change cannot be implemented as a skill.
This is the most important invariant for system stability. If the harness grows fat, it becomes:
- Harder to verify for security
- Harder to debug when things go wrong
- Harder to maintain across versions
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *modularity-protected-paths*
'("harness/" "opencortex.asd")
"Paths that constitute the unbreakable core of the system.
Any action targeting these paths must include a :modularity-justification.
This list is project-specific and should be configured at boot time.")
Any action targeting these paths must include a :modularity-justification
explaining why the change cannot be implemented as a skill.
The Thin Harness principle: What belongs in the harness?
- Core signal processing (Perceive-Reason-Act loop)
- Memory and persistence primitives
- Protocol definition and validation
- Skills register and dispatch
What belongs in skills?
- Policy and security
- LLM integration
- Domain-specific functionality
- New actuators")
(defun policy-check-modularity (action context)
"Blocks modifications to the system's protected core unless justified."
"Blocks modifications to the system's protected core unless justified.
MODULARITY CHECK:
1. If the action targets a protected path
2. And no :modularity-justification is provided
3. Then block with an explanation
The justification should explain WHY the change cannot be a skill.
Common valid reasons:
- The change fixes a bug in the harness itself
- The change adds a primitive that skills cannot implement
- The change is required for security hardening
Invalid reasons:
- 'It's easier to modify the harness'
- 'Skills are too slow'
- 'I want to keep it all in one place'"
(declare (ignore context))
(let* ((payload (getf action :payload))
(target-file (or (getf payload :file) (getf payload :filename)))
(target-file (or (getf payload :file)
(getf payload :filename)))
(justification (or (getf payload :modularity-justification)
(getf payload :MODULARITY-JUSTIFICATION))))
(when (and target-file
(some (lambda (path) (search path target-file)) *modularity-protected-paths*)
(some (lambda (path) (search path target-file))
*modularity-protected-paths*)
(not justification))
(return-from policy-check-modularity
(list :type :LOG
:payload (list :level :error
:text "POLICY [Modularity]: Modification to protected core path blocked. Provide :modularity-justification explaining why this cannot be a skill."
:blocked-path target-file))))
action))
action)
#+end_src
* The Policy Explanation Engine
When the policy gate modifies or blocks an action, it must tell the user *why*. This function formats a human-readable rationale from the invariant that triggered the interception.
** 5. Technical Mastery & Mentorship
*The maxim: "Teaching is the highest form of assistance."*
The agent's goal is not to "do it for the user," but to "empower the user." Every autonomous action must be explained at a level that increases the user's technical understanding.
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *mentorship-required-actions*
'(:create-skill :eval :modify-file :write-file :replace
:rename-file :delete-file :shell :create-note)
"Actions that trigger the Mentorship invariant.
These are high-impact actions that should come with explanations
not just for the user, but for future debugging and maintenance.")
(defun policy-check-mentorship (action context)
"Blocks high-impact actions that lack a mentorship note.
MENTORSHIP CHECK:
1. If the action is in *mentorship-required-actions*
2. Or if the action calls shell/eval/repair-file tools
3. Then require :mentorship-note explaining what and why
The mentorship note should be:
- Concise (1-2 sentences)
- Educational (explain the principle, not just the action)
- Actionable (help the user understand the outcome)"
(declare (ignore context))
(let* ((payload (getf action :payload))
(act (or (getf payload :action)
(getf action :action)))
(note (or (getf payload :mentorship-note)
(getf payload :MENTORSHIP-NOTE)))
(target (or (getf action :target)
(getf action :TARGET)))
(tool (when (eq target :tool)
(getf payload :tool))))
(when (or (member act *mentorship-required-actions*)
(member tool '("shell" "eval" "repair-file")))
(unless note
(return-from policy-check-mentorship
(list :type :LOG
:payload (list :level :error
:text "POLICY [Mentorship]: High-impact action missing :mentorship-note. Explain what you are doing and why. Blocked.")))))
action)
#+end_src
** 6. Long-Term Sustainability
*The maxim: "Build for the 100-year horizon."*
The Memex should be functional even when:
- Internet is unavailable
- Cloud services are discontinued
- Hardware platforms change
This means preferring local, energy-efficient architectures over cloud-dependent ones.
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defvar *cloud-only-backends* '(:openrouter :openai :anthropic :groq :gemini-api)
"Backends requiring internet connection and external infrastructure.
These are acceptable as fallbacks when local inference is unavailable,
but should be logged as sustainability debt for tracking purposes.")
(defun policy-check-sustainability (action context)
"Logs sustainability debt when action relies on cloud-only infrastructure.
Does NOT block—this is informational, not prohibitive.
Cloud usage is acceptable tactically (when local models fail),
but every cloud usage should be a conscious decision, not a default."
(let* ((payload (getf context :payload))
(backend (getf payload :backend))
(provider (getf payload :provider))
(when (or (member backend *cloud-only-backends*)
(member provider *cloud-only-backends*))
(harness-log "POLICY [Sustainability]: Cloud provider '~a' used. Logged as sustainability debt."
(or backend provider))
(return-from policy-check-sustainability
(list :type :LOG
:payload (list :level :warn
:text (format nil "Sustainability Debt: Reliance on cloud provider '~a'. Consider Ollama or local inference."
(or backend provider))))))
action)
#+end_src
* Policy Explanation Engine
When the policy gate blocks or modifies an action, it must tell the user *why*. This creates an auditable log of every policy decision.
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defun policy-explain (invariant-key message &optional original-action)
"Formats a policy decision into an auditable explanation plist.
INVARIANT-KEY is one of :transparency, :autonomy, :bloat, :modularity, :mentorship, :sustainability.
MESSAGE is a human-readable string.
ORIGINAL-ACTION is the action that was blocked or modified."
INVARIANT-KEY is one of:
:transparency, :autonomy, :bloat, :modularity, :mentorship, :sustainability
MESSAGE is a human-readable string explaining the decision.
ORIGINAL-ACTION is the action that was blocked or modified.
Returns a REQUEST plist addressed to the original source,
containing the explanation and original action for transparency."
(list :type :REQUEST
:target (or (ignore-errors (getf (getf original-action :meta) :source)) :cli)
:target (or (ignore-errors
(getf (getf original-action :meta) :source))
:cli)
:payload (list :action :message
:text (format nil "[POLICY ~a] ~a" invariant-key message)
:explanation (format nil "Invariant: ~a | Rationale: ~a" invariant-key message)
:explanation (format nil "Invariant: ~a | Rationale: ~a"
invariant-key message)
:original-action original-action)))
#+end_src
* The Policy Gate
The main deterministic entry point for the policy skill. It runs invariant checks in priority order. If a check returns a blocking LOG event, the gate immediately yields with an explanation. If a check returns a modified action (e.g., a warning wrapper), the modified action is passed down the chain.
The gate also attempts to delegate to Engineering Standards, but it does so robustly: it searches multiple candidate package names and falls back gracefully if the standards skill is not loaded.
** Running Invariant Checks
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defun policy-run-invariant-checks (action context)
"Runs all invariant checks in priority order. Returns the final action,
a blocking LOG event, or a warning wrapper."
"Runs all invariant checks in priority order.
Priority order (from *policy-invariant-priorities*):
1. Transparency (500) - blocks non-transparent actions
2. Autonomy (400) - warns on proprietary dependencies
3. Bloat (300) - warns on oversized skills
4. Modularity (250) - blocks unprotected core modifications
5. Mentorship (200) - blocks unexplained high-impact actions
6. Sustainability (100) - warns on cloud dependencies
Returns:
- The final action (possibly modified by checks)
- A blocking LOG event (if any check returned :error level)
- A warning wrapper (if checks returned :warn level but no blocks)"
(let ((checks '(policy-check-transparency
policy-check-autonomy
policy-check-bloat
policy-check-modularity
policy-check-mentorship
policy-check-sustainability)))
(dolist (check-fn checks action)
(let ((result (funcall check-fn action context)))
;; If the check returned a LOG event, treat it as a block/warning
;; If the check returned a LOG/EVENT, interpret it
(when (and (listp result)
(member (getf result :type) '(:LOG :EVENT)))
(let ((level (getf (getf result :payload) :level)))
(cond ((eq level :error)
;; Hard block: return the log event directly
(return-from policy-run-invariant-checks result))
(t
;; Warning: log it, but continue with the original action
(harness-log "~a" (getf (getf result :payload) :text))))))))))
(let ((level (getf (getf result :payload) :level)))
(cond
;; Hard block: error level stops processing immediately
((eq level :error)
(return-from policy-run-invariant-checks result))
;; Soft warning: log but continue with original action
(t
(harness-log "~a" (getf (getf result :payload) :text)))))))))
action)
#+end_src
** Finding Engineering Standards
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defun policy-find-engineering-standards-gate ()
"Searches for the Engineering Standards gate across known jailed package names.
Returns the function symbol, or NIL if unavailable."
The standards skill may be in opencortex-contrib submodule,
so we search multiple possible package names with graceful fallback.
Returns the function symbol, or NIL if unavailable."
(dolist (pkg-name '(:opencortex.skills.org-skill-engineering-standards
:opencortex.skills.org-skill-engineering
:opencortex.skills.engineering-standards)
nil)
(let ((pkg (find-package pkg-name)))
(when pkg
(let ((sym (find-symbol "ENGINEERING-STANDARDS-GATE" pkg)))
(when (and sym (fboundp sym))
(return (symbol-function sym))))))))
#+end_src
** Main Policy Gate
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defun policy-deterministic-gate (action context)
"The main policy gate. Runs invariant checks, then delegates to engineering standards if available.
Never returns NIL silently; always returns an action or an auditable log event."
"The main policy gate entry point.
This function is registered as the deterministic-fn for the policy skill.
It runs invariant checks, then delegates to engineering standards if loaded.
IMPORTANT: Never returns NIL silently. Always returns either:
- An action (possibly modified)
- A blocking LOG event with explanation
- A warning wrapper with explanation"
;; Step 1: Run invariant checks
(let ((current-action (policy-run-invariant-checks action context)))
;; If an invariant returned a blocking log, do not proceed further
;; Step 2: If an invariant blocked the action, stop here
(when (and (listp current-action)
(member (getf current-action :type) '(:LOG :EVENT))
(eq (getf (getf current-action :payload) :level) :error))
(return-from policy-deterministic-gate current-action))
;; Delegate to Engineering Standards if loaded
;; Step 3: Delegate to Engineering Standards if loaded
(let ((eng-gate (policy-find-engineering-standards-gate)))
(when eng-gate
(setf current-action (funcall eng-gate current-action context))))
current-action))
#+end_src
* Operational Mandates
Every action performed by an agent in this environment must also adhere to the Engineering Standards. The policy skill evaluates every context (trigger is always true) because invariants are universal.
* Skill Registration
** Skill Registration
#+begin_src lisp :tangle ../library/gen/org-skill-policy.lisp
(defskill :skill-policy
:priority 500
@@ -305,6 +555,29 @@ Every action performed by an agent in this environment must also adhere to the E
:deterministic #'policy-deterministic-gate)
#+end_src
* Quick Reference
** Invariant Quick Reference
| Invariant | Blocks? | Trigger |
|-----------|---------|---------|
| Transparency | Yes | Missing `:explanation` on user-facing actions |
| Autonomy | No | Action references proprietary domain |
| Bloat | No | Skill file exceeds 50KB |
| Modularity | Yes | Modification to `harness/` without justification |
| Mentorship | Yes | High-impact action without `:mentorship-note` |
| Sustainability | No | Action uses cloud-only provider |
** Required Fields by Action Type
| Action | Required Field | Purpose |
|--------|---------------|---------|
| User message | `:explanation` | Transparency |
| Core modification | `:modularity-justification` | Modularity |
| Skill creation | `:mentorship-note` | Mentorship |
| File write | `:mentorship-note` | Mentorship |
* See Also
- [[file:org-skill-engineering-standards.org][Engineering Standards]] (if loaded)
- [[file:../harness/act.org][Act Stage]] (where the Bouncer and Policy gates are invoked)
- [[file:org-skill-engineering-standards.org][Engineering Standards]] (if loaded in opencortex-contrib)
- [[file:../harness/act.org][Act Stage]] - Where Policy and Bouncer gates are invoked
- [[file:../harness/manifest.org][Manifest]] - The Thin Harness philosophy