data: add cookbook recipes + feature note from session work

ober

581c6771f6a7a09c65852d344044be192033a5f4

diff --git a/data/cookbooks.sexp b/data/cookbooks.sexp
index 1921b81..a7489d6 100644
--- a/data/cookbooks.sexp
+++ b/data/cookbooks.sexp
@@ -4778,4 +4778,76 @@
      "sls" "prelude")
    ("title"
      .
-     "Parse JSON arrays and read optional fields in a .sls library")))
+     "Parse JSON arrays and read optional fields in a .sls library"))
+ (("code"
+    .
+    "(import (jerboa prelude))\n(import (chezscheme))\n(import (std text yaml))\n\n(def sample \"sources:\\n  - name: src-a\\n    bucket: s3://bucket\\n    path: prefix\\n    enabled: true\\n\")\n\n(def doc (safe-yaml-load-string sample))\n(def sources (cdr (assoc \"sources\" doc)))\n(def first-source (car sources))\n(displayln (cdr (assoc \"name\" first-source)))\n(displayln (cdr (assoc \"enabled\" first-source)))") ("id" . "parse-yaml-sources-alist")
+   ("imports" "jerboa prelude" "chezscheme" "std text yaml")
+   ("notes"
+     .
+     "safe-yaml-load-string returns ordinary Scheme data for simple YAML: top-level mappings are alists with string keys, sequences are lists, and booleans become #t/#f. Use string keys with assoc/alist helpers, not symbols.")
+   ("tags" "yaml" "std text yaml" "safe-yaml-load-string"
+     "alist" "sources")
+   ("title" . "Parse YAML into string-keyed alists"))
+ (("code"
+    .
+    "(import (jerboa prelude))\n(import (chezscheme))\n\n(def *yaml-loader* #f)\n\n(def (yaml-loader)\n  (unless *yaml-loader*\n    (set! *yaml-loader*\n      (eval 'safe-yaml-load-string (environment '(std text yaml)))))\n  *yaml-loader*)\n\n(def doc ((yaml-loader) \"sources:\\n  - name: src-a\\n\"))\n(displayln (cdr (assoc \"sources\" doc)))") ("id" . "lazy-stdlib-binding-in-use-file")
+   ("imports" "jerboa prelude" "chezscheme")
+   ("notes"
+     .
+     "jsh's ,use path reads and evaluates top-level forms and may skip import forms. For a loadable helper that needs a non-prelude module, resolve the binding with (eval 'name (environment '(module path))) at runtime and cache the procedure. This also keeps the file loadable until the function is first used.")
+   ("tags" "jsh" "use" "eval" "environment" "stdlib"
+     "dynamic binding")
+   ("title"
+     .
+     "Resolve stdlib bindings lazily for jsh ,use helpers"))
+ (("code"
+    .
+    "(import (chezscheme)\n        (jerboa-aws s3 api)\n        (jerboa-aws s3 objects)\n        (jerboa-aws request))\n\n(define (write-bytes path bv)\n  (call-with-port\n    (open-file-output-port path (file-options no-fail) (buffer-mode block))\n    (lambda (out)\n      (put-bytevector out bv))))\n\n(define (download-object-bytes client bucket key output-path)\n  (let ([req #f])\n    (dynamic-wind\n      (lambda () (void))\n      (lambda ()\n        (set! req\n          (s3-request/check client\n            'verb: \"GET\"\n            'bucket: bucket\n            'key: key))\n        (write-bytes output-path (request-content req)))\n      (lambda ()\n        (when req (request-close req))))))\n\n(define client (S3Client 'profile: \"default\" 'region: \"us-east-1\"))\n(define page (list-objects-v2 client \"my-bucket\" 'prefix: \"events/dt=2026-06-01/\" 'max-keys: 1000))\n\n;; XML responses are hash tables with symbol keys.\n(define contents (hashtable-ref page 'Contents '()))\n(define first-key\n  (cond\n    [(and (pair? contents) (hashtable? (car contents)))\n     (hashtable-ref (car contents) 'Key #f)]\n    [(hashtable? contents)\n     (hashtable-ref contents 'Key #f)]\n    [else #f]))\n\n(when first-key\n  (download-object-bytes client \"my-bucket\" first-key \"downloaded-object.bin\"))") ("id" . "aws-s3-list-download-bytes")
+   ("imports"
+     "(chezscheme)"
+     "(jerboa-aws s3 api)"
+     "(jerboa-aws s3 objects)"
+     "(jerboa-aws request)")
+   ("notes"
+     .
+     "Use request-content rather than get-object/request-text for Parquet, gzip, and other binary S3 objects. Use open-file-output-port with no transcoder and put-bytevector; call-with-output-file creates a textual port, and put-bytevector will fail. Close the request in dynamic-wind so errors during file writing do not leak the HTTP handle. list-objects-v2 requires the S3 request helper to sign and include query parameters.")
+   ("tags" "jerboa-aws" "s3" "request-content" "binary-file"
+     "list-objects-v2" "open-file-output-port")
+   ("title"
+     .
+     "List S3 Objects and Download Binary Content with jerboa-aws"))
+ (("code"
+    .
+    "#!/usr/bin/env jsh\n,policy-reset\n,cache ephemeral\n,limit fsize 2g\n,exec /bin\n,exec /usr/bin\n,exec /opt\n,exec node\n,run-policy -- node \"$@\"\n") ("id" . "node-wrapper-without-default-pids-limit")
+   ("imports")
+   ("notes"
+     .
+     "Do not put a low default `,limit pids` in generic Node-family wrappers that may run on macOS. Darwin's process-count rlimit is user-wide, so a cap such as 256 can make nested Node child_process.spawn calls fail with EAGAIN when the account already has more processes than the cap. On Linux, add `,limit pids N` only in a site-specific wrapper when parent-side pids supervision is desired.")
+   ("tags" "jsh" "limits" "pids" "macos" "node" "EAGAIN")
+   ("title"
+     .
+     "Avoid default pids caps in Node-family policy wrappers on macOS"))
+ (("code"
+    .
+    "#!/usr/bin/env jsh\n,policy-reset\n,read @project\n,write @project\n,read /bin\n,read /etc\n,read /opt\n,read /usr\n,read /private/var/db\n,read ~/Library/Application\\ Support/Claude\n,read ~/.claude.json\n,write ~/.claude.json\n,read ~/.claude\n,write ~/.claude\n,net *:443\n,home real\n,cache ephemeral\n,limit fsize 2g\n,exec claude\n,run-policy -- claude \"$@\"\n") ("id" . "claude-macos-wrapper-runtime-grants") ("imports")
+   ("notes"
+     .
+     "On macOS, Claude Code can start under a Seatbelt-backed jsh policy but model calls using the normal logged-in auth path need read access to `~/Library/Application Support/Claude`. Native startup also needs read access to `/private/var/db`; without it `claude --version` may print `error: An unknown error occurred (Unexpected)` or exit/trap under the sandbox. Keep `npx` denied unless a site-specific wrapper intentionally allows configured hooks.")
+   ("tags" "jsh" "claude" "macos" "seatbelt" "wrapper"
+     "run-policy")
+   ("title"
+     .
+     "Claude policy wrapper grants needed on macOS Seatbelt"))
+ (("code"
+    .
+    "(import (jerboa prelude))\n\n;; To bind a value AND require it to satisfy a predicate inside `match`,\n;; wrap the predicate test and the binding variable in `and`:\n;;   (and (? pred) var)   ;; correct: binds var when (pred val) is true\n;; The bare two-arg form (? pred var) silently FAILS to match (it never\n;; binds), so such clauses fall through to a later pattern or the wildcard.\n\n(def (classify x)\n  (match x\n    ((and (? integer?) n) (list 'int n))\n    ((and (? string?) s)  (list 'str s))\n    ((list (and (? integer?) a) (and (? integer?) b)) (list 'pair a b))\n    (_ 'other)))\n\n(displayln (classify 20))         ;; => (int 20)\n(displayln (classify \"hi\"))       ;; => (str \"hi\")\n(displayln (classify (list 3 4))) ;; => (pair 3 4)\n(displayln (classify 'sym))       ;; => other") ("id" . "match-predicate-bind")
+   ("imports" "(jerboa prelude)")
+   ("notes"
+     .
+     "Jerboa's match predicate-with-binding is (and (? pred) var) -- the Racket/Gerbil style -- NOT (? pred var), which the AGENTS.md quick-reference shows but which silently no-matches in Jerboa (compiles fine, just never binds, so clauses fall through). `(? pred)` alone (no bind) works for a pure type test. The (and (? pred) var) form nests inside (list ...) and (cons ...) patterns. String literals and (or \"a\" \"b\") patterns work as written. Note that an unadorned identifier is always a binding pattern (matches anything) -- to compare against a named constant's VALUE, use a guard instead: (n (where (= n DNS-T-A)) ...). Verified on Jerboa/Chez via jerboa_eval.")
+   ("tags" "match" "pattern-matching" "predicate" "and"
+     "prelude" "guard")
+   ("title"
+     .
+     "match: bind a predicate-checked value with (and (? pred) var)")))
diff --git a/data/features.sexp b/data/features.sexp
index daba777..a11a4ab 100644
--- a/data/features.sexp
+++ b/data/features.sexp
@@ -1088,4 +1088,40 @@
    ("use_case"
      .
      "Before running an expensive jsh binary build, verify hand-written .sls modules with the same compiler path that jerbuild build will use.")
+   ("votes" . 0))
+ (("description"
+    .
+    "When verifying a 650-line user .ss file, jerboa_verify and jerboa_compile_check failed with an internal string-ref invalid index exception against the full source buffer instead of returning a syntax or compile diagnostic. I had to fall back to jerbuild exec smoke tests and manual line inspection.")
+   ("estimated_token_reduction"
+     .
+     "~1000 tokens per failure by avoiding source dumps and fallback shell checks")
+   ("example_scenario"
+     .
+     "jerboa_verify on search.ss reported `Exception in string-ref: 23076 is not a valid index` and dumped the entire source string, while `jerbuild exec search.ss` loaded successfully.")
+   ("id" . "verify-large-file-error-report")
+   ("impact" . "medium")
+   ("tags" "verify" "compile-check" "large-file" "diagnostics")
+   ("title"
+     .
+     "Make jerboa_verify report large-file scanner failures cleanly")
+   ("use_case"
+     .
+     "Validating nontrivial loadable helper files where MCP verification should be the primary check.")
+   ("votes" . 0))
+ (("description"
+    .
+    "jerboa_verify crashed with an out-of-range string-ref while verifying a large user-facing .ss file. The caller then had to fall back to direct scheme --script checks, losing the normal combined verify report.")
+   ("estimated_token_reduction"
+     .
+     "~300-800 tokens per failure by avoiding fallback command checks and manual explanation.")
+   ("example_scenario"
+     .
+     "Verifying search.ss (~34 KB) raised: Exception in string-ref: 34389 is not a valid index. The same file loaded successfully via scheme --script and jsh ,use.")
+   ("id" . "verify-large-file-range-guard")
+   ("impact" . "medium")
+   ("tags" "verify" "large-file" "string-ref" "diagnostics")
+   ("title" . "Make jerboa_verify robust on large files")
+   ("use_case"
+     .
+     "When validating larger Jerboa scripts or generated files, jerboa_verify should return a structured parse/compile result instead of an internal exception.")
    ("votes" . 0)))