v0.7.2: safe-tool read-only allowlist — TDD

Read-only cognitive tools auto-pass dispatcher-check unconditionally.
Added :read-only-p slot to cognitive-tool struct, :read-only-p keyword
to def-cognitive-tool macro, tool-read-only-p registry lookup.

- core-package: struct + macro + tool-read-only-p function
- security-dispatcher: early auto-pass in dispatcher-check, 2 new tests
- programming-tools: 7 tools marked :read-only-p t (search-files,
  find-files, read-file, list-directory, eval-form, run-tests,
  org-find-headline)
- Dispatcher: 38/38
This commit is contained in:
2026-05-08 16:28:10 -04:00
parent bec894ca4f
commit d2d61c5b44
6 changed files with 140 additions and 24 deletions

View File

@@ -48,6 +48,7 @@ Searches file contents recursively under a directory using regex pattern matchin
((:name "pattern" :description "The regex pattern to search for." :type "string")
(:name "path" :description "Directory to search recursively." :type "string")
(:name "include" :description "Optional glob filter for filenames (e.g. \"*.lisp\")." :type "string"))
:read-only-p t
:guard nil
:body (lambda (args)
(block nil
@@ -86,9 +87,10 @@ Glob file matching using SBCL's ~directory~.
#+begin_src lisp
(def-cognitive-tool find-files
"Find files matching a glob pattern under a directory."
((:name "pattern" :description "Glob pattern (e.g. \"*.lisp\", \"core-*\")." :type "string")
"Find files matching a glob pattern."
((:name "pattern" :description "The glob pattern to match (e.g. \"*.lisp\")." :type "string")
(:name "path" :description "Directory to search in." :type "string"))
:read-only-p t
:guard nil
:body (lambda (args)
(block nil
@@ -116,6 +118,7 @@ Reads a file into a string. Supports optional ~:start~ and ~:limit~ for partial
((:name "filepath" :description "Path to the file to read." :type "string")
(:name "start" :description "Optional: line number to start reading from (1-based)." :type "integer")
(:name "limit" :description "Optional: maximum number of lines to read." :type "integer"))
:read-only-p t
:guard (lambda (args) (declare (ignore args)) nil)
:body (lambda (args)
(block nil
@@ -169,8 +172,9 @@ Lists the contents of a directory, optionally filtered by a glob pattern.
(def-cognitive-tool list-directory
"List the contents of a directory."
((:name "path" :description "Directory path to list." :type "string")
(:name "pattern" :description "Optional glob filter (e.g. \"*.org\")." :type "string"))
:guard nil
(:name "pattern" :description "Optional glob filter (e.g. \"*.org\")." :type "string"))
:read-only-p t
:guard nil
:body (lambda (args)
(block nil
(let* ((path (getf args :path))
@@ -224,6 +228,7 @@ Evaluates a Lisp expression in the running image. Binds ~*read-eval*~ to nil for
(def-cognitive-tool eval-form
"Evaluate a Lisp expression in the running image and return the result."
((:name "code" :description "The Lisp expression to evaluate as a string." :type "string"))
:read-only-p t
:guard nil
:body (lambda (args)
(block nil
@@ -246,6 +251,7 @@ Runs FiveAM test suites. Without arguments, runs all tests via ~fiveam:run-all-t
(def-cognitive-tool run-tests
"Run FiveAM tests. With no arguments, runs all test suites."
((:name "test-name" :description "Optional: specific test name to run. If nil, runs all tests." :type "string"))
:read-only-p t
:guard nil
:body (lambda (args)
(block nil
@@ -271,6 +277,7 @@ Finds Org headlines in the memory store by ID property or title substring match.
"Find an Org headline by ID or title in the memory store."
((:name "id" :description "Optional: Org ID property to search for." :type "string")
(:name "title" :description "Optional: headline title to search for (case-insensitive substring)." :type "string"))
:read-only-p t
:guard nil
:body (lambda (args)
(block nil