Update cookbook/feature registry data

ober

bd368249c54a09d3e4276b9de6c840b43761671a

diff --git a/data/cookbooks.sexp b/data/cookbooks.sexp
index c3fe40e..1921b81 100644
--- a/data/cookbooks.sexp
+++ b/data/cookbooks.sexp
@@ -2254,9 +2254,7 @@
    ("related" "gerbil-migration-sort-order" "jerboa-sort")
    ("tags" "sort" "std sort" "import" "shadow" "argument-order"
      "prelude")
-   ("title"
-     .
-     "Jerboa sort uses list-first order"))
+   ("title" . "Jerboa sort uses list-first order"))
  (("code"
     .
     ";; SHA256 hash of string or bytevector\n(import (std crypto native))\n\n(define (sha256 data)\n  (native-digest 'sha256\n    (if (string? data) (string->utf8 data) data)))\n\n;; HMAC-SHA256 — key and data can be strings or bytevectors\n(define (hmac-sha256 key data)\n  (native-hmac-sha256\n    (if (string? key)  (string->utf8 key)  key)\n    (if (string? data) (string->utf8 data) data)))\n\n;; Returns bytevectors. To get hex string:\n(define (bytes->hex bv)\n  (apply string-append\n    (map (lambda (b) (format \"~2,'0x\" b))\n         (bytevector->u8-list bv))))\n\n(bytes->hex (sha256 \"hello world\"))\n;; => \"b94d27b9934d3e08a52e52d7da7dabfac484efe04294e576fbc9a08f\"...") ("id" . "std-crypto-native-sha256-hmac")
@@ -4734,13 +4732,10 @@
      .
      "std/ffi is a v0.19 replacement for :std/foreign. def-C generates a Gambit ___BEGIN_C_LINKAGE block with inline C code plus the Scheme wrapper. The C code receives raw Gambit object pointers named ___ARG1, ___ARG2, ... which def-C unwraps to the correct C types per the :type annotations before passing as $1, $2, .... Use C-ffi-macrology once per compilation unit to get ___U8VECTOR_AS and ___TRAP_ERRNO helpers. The require guard ensures the form is only compiled for C-target builds.")
    ("tags" "ffi" "C" "def-C" "C-include" "foreign" "v0.19")
-   ("title"
-     .
-     "v0.19: FFI macrology with def-C and C-include"))
+   ("title" . "v0.19: FFI macrology with def-C and C-include"))
  (("code"
     .
-    ";; support/build-check.ss\n#!chezscheme\n;;; Import-only build entrypoint: compile the same modules as main.ss,\n;;; but do not call cli-main or start the app.\n(import (chezscheme)\n        (myapp core config)\n        (myapp core agent)\n        (myapp ui cli))\n\n;; Makefile\nJERBUILD ?= jerbuild\nJH := $(shell $(JERBUILD) --jerboa-home 2>/dev/null)\nLIBDIRS := --libdirs ./lib:$(JH)/lib\n\nbuild:\n\t$(JERBUILD) compile $(LIBDIRS) support/build-check.ss\n")
-   ("id" . "jerbuild-import-only-build-check") ("imports")
+    ";; support/build-check.ss\n#!chezscheme\n;;; Import-only build entrypoint: compile the same modules as main.ss,\n;;; but do not call cli-main or start the app.\n(import (chezscheme)\n        (myapp core config)\n        (myapp core agent)\n        (myapp ui cli))\n\n;; Makefile\nJERBUILD ?= jerbuild\nJH := $(shell $(JERBUILD) --jerboa-home 2>/dev/null)\nLIBDIRS := --libdirs ./lib:$(JH)/lib\n\nbuild:\n\t$(JERBUILD) compile $(LIBDIRS) support/build-check.ss\n") ("id" . "jerbuild-import-only-build-check") ("imports")
    ("notes"
      .
      "jerbuild compile executes the script after compiling it. If main.ss calls cli-main, a build target can accidentally start the TUI/CLI or hang. Use an import-only entrypoint that imports the same top-level modules needed to force compilation, but performs no application action.")
@@ -4751,8 +4746,7 @@
      "Compile a Jerboa project without running its CLI entrypoint"))
  (("code"
     .
-    ";; support/sqlite-bundled/Cargo.toml\n[package]\nname = \"app-sqlite-bundled\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"staticlib\"]\n\n[dependencies]\nlibsqlite3-sys = { version = \"0.30\", features = [\"bundled\"] }\n\n;; support/sqlite-bundled/src/lib.rs\n#[no_mangle]\npub extern \"C\" fn app_sqlite_bundled_anchor() -> i32 {\n    unsafe { libsqlite3_sys::sqlite3_libversion_number() }\n}\n\n;; .jerbuild\n(entry \"main.ss\")\n(output \"app\")\n(ffi-symbols \"support/ffi-symbols.list\")\n(extra-sources\n  (\"vendor/jerboa-sqlite/jerboa_sqlite_shim.c\" cflags: \"-Isupport\"))\n(extra-archives\n  \"support/sqlite-bundled/target/release/libapp_sqlite_bundled.a\")\n\n;; Makefile\nsupport/sqlite-bundled/target/release/libapp_sqlite_bundled.a:\n\tcargo build --manifest-path support/sqlite-bundled/Cargo.toml --release\n\nbinary: support/sqlite-bundled/target/release/libapp_sqlite_bundled.a\n\tjerbuild build --config .jerbuild --os-libs \"-lm -ldl -lpthread -luuid -lncurses -lstdc++\"\n")
-   ("id" . "jerbuild-bundled-sqlite-shim") ("imports")
+    ";; support/sqlite-bundled/Cargo.toml\n[package]\nname = \"app-sqlite-bundled\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"staticlib\"]\n\n[dependencies]\nlibsqlite3-sys = { version = \"0.30\", features = [\"bundled\"] }\n\n;; support/sqlite-bundled/src/lib.rs\n#[no_mangle]\npub extern \"C\" fn app_sqlite_bundled_anchor() -> i32 {\n    unsafe { libsqlite3_sys::sqlite3_libversion_number() }\n}\n\n;; .jerbuild\n(entry \"main.ss\")\n(output \"app\")\n(ffi-symbols \"support/ffi-symbols.list\")\n(extra-sources\n  (\"vendor/jerboa-sqlite/jerboa_sqlite_shim.c\" cflags: \"-Isupport\"))\n(extra-archives\n  \"support/sqlite-bundled/target/release/libapp_sqlite_bundled.a\")\n\n;; Makefile\nsupport/sqlite-bundled/target/release/libapp_sqlite_bundled.a:\n\tcargo build --manifest-path support/sqlite-bundled/Cargo.toml --release\n\nbinary: support/sqlite-bundled/target/release/libapp_sqlite_bundled.a\n\tjerbuild build --config .jerbuild --os-libs \"-lm -ldl -lpthread -luuid -lncurses -lstdc++\"\n") ("id" . "jerbuild-bundled-sqlite-shim") ("imports")
    ("notes"
      .
      "This keeps user repos buildable with jerbuild plus a C compiler and Rust/Cargo, without requiring system sqlite headers or libsqlite3 packages. Put a minimal sqlite3.h in support/ if the shim only needs a small API surface, add -Isupport on the shim source, and list the bundled Rust static archive in extra-archives so sqlite symbols are available at final link.")
@@ -4770,4 +4764,18 @@
      "Use `(jerboa prelude)` and `get-datum` for manifest/data files. Avoid bare `read` in validators so security tooling can distinguish data parsing from eval-like REPL reads. Use `let*` when reading multiple datums from the same port so the reads occur in order.")
    ("tags" "manifest" "get-datum" "file-io" "validation"
      "prelude")
-   ("title" . "Validate a single S-expression manifest file")))
+   ("title" . "Validate a single S-expression manifest file"))
+ (("code"
+    .
+    "(library (demo json-array-fields)\n  (export labels-json)\n  (import (chezscheme)\n          (only (jerboa prelude) string->json-object json-object->string))\n\n  (define (json-string-field row key)\n    ;; string->json-object returns JSON objects as Chez hashtables.\n    ;; In .sls libraries, hashtable-ref is WPO-safe for optional fields.\n    (let ([value (hashtable-ref row key #f)])\n      (and (string? value) value)))\n\n  (define (labels-json json-text)\n    (let ([rows (string->json-object json-text)])\n      (unless (list? rows)\n        (error 'labels-json \"expected a JSON array\"))\n      (json-object->string\n        (map (lambda (row)\n               (let ([out (make-hashtable string-hash string=?)])\n                 (hashtable-set! out \"label\"\n                   (or (json-string-field row \"label\") \"\"))\n                 out))\n             rows)))))") ("id" . "parse-json-array-hashtable-ref")
+   ("imports"
+     "(chezscheme)"
+     "(only (jerboa prelude) string->json-object json-object->string)")
+   ("notes"
+     .
+     "`string->json-object` can parse a top-level JSON array; each object row is a Chez hashtable keyed by strings. Avoid `(hash-get row key #f)` in hand-written `.sls` libraries: it may pass lightweight checks but fail WPO/binary compilation as invalid syntax. Use Chez `(hashtable-ref row key #f)` for optional field reads, and `json-object->string` accepts Chez hashtables when writing JSON back out.")
+   ("tags" "json" "string->json-object" "hashtable-ref" "wpo"
+     "sls" "prelude")
+   ("title"
+     .
+     "Parse JSON arrays and read optional fields in a .sls library")))
diff --git a/data/features.sexp b/data/features.sexp
index e993c14..daba777 100644
--- a/data/features.sexp
+++ b/data/features.sexp
@@ -1072,4 +1072,20 @@
    ("use_case"
      .
      "Validating tools/check-system-manifest.ss hit `Exception in string-ref: 12290 is not a valid index` even though the script runs and security_scan passes.")
+   ("votes" . 0))
+ (("description"
+    .
+    "jerboa_verify reported no issues for a .sls file that later failed during jerbuild binary WPO compilation with `invalid syntax (hash-get row key #f)`. A verification mode that runs the same expansion/WPO path as binary builds, or at least flags syntax accepted by lightweight checks but rejected by WPO, would catch these before a full binary build.")
+   ("estimated_token_reduction"
+     .
+     "~1000-2000 tokens per WPO-only compile failure")
+   ("example_scenario"
+     .
+     "A pass.sls change using `(hash-get row key #f)` passed jerboa_verify and module compilation but failed in `make macos` during WPO. A WPO verify mode would have pointed directly at the issue earlier.")
+   ("id" . "verify-wpo-mode") ("impact" . "medium")
+   ("tags" "verify" "wpo" "binary-build" "compile-check")
+   ("title" . "Add WPO/binary compile mode to jerboa_verify")
+   ("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)))