build: repair portable platform artifacts

ober

9586691de3c5c2db6759a559d674b19801de4eab

diff --git a/build-jcode-cross.ss b/build-jcode-cross.ss
index c4b0cbc..3f45ab0 100644
--- a/build-jcode-cross.ss
+++ b/build-jcode-cross.ss
@@ -62,6 +62,7 @@
 
 (define cross-prefix (format "~a/.chez-cross-~a" jerboa-home chez-machine))
 (define xpatch       (format "~a/build/chez/xc-~a/s/xpatch" jerboa-home chez-machine))
+(define use-xpatch?  (not (string=? (symbol->string (machine-type)) chez-machine)))
 (define cross-cc     (or (getenv "CROSS_CC") (list-ref arch-row 2)))
 
 (define output       (list-ref arch-row 4))
@@ -104,7 +105,7 @@
   (unless (file-exists? p)
     (error 'build-jcode-cross "missing file" p)))
 
-(require-file xpatch)
+(when use-xpatch? (require-file xpatch))
 (require-file (format "~a/libkernel.a"  cross-csv-dir))
 (require-file (format "~a/scheme.h"     cross-csv-dir))
 (require-file (format "~a/petite.boot"  cross-csv-dir))
@@ -114,7 +115,8 @@
 (printf "==> build-jcode-cross~n")
 (printf "    JERBOA_HOME:   ~a~n" jerboa-home)
 (printf "    cross csv-dir: ~a~n" cross-csv-dir)
-(printf "    xpatch:        ~a~n" xpatch)
+(printf "    xpatch:        ~a~n"
+        (if use-xpatch? xpatch "not needed (host and target machine types match)"))
 (printf "    cross-cc:      ~a~n" cross-cc)
 (printf "    output:        ~a~n" output)
 (printf "    features:      ~a~n~n" cargo-features)
@@ -263,8 +265,11 @@
 
 ;; ── Stage 1: load xpatch (target=ta6le emit mode) ──────────────────────────
 (define orig-libdirs (library-directories))
-(printf "==> [1/6] loading xpatch (compiler -> ~a emit mode)~n" chez-machine)
-(load xpatch)
+(if use-xpatch?
+    (begin
+      (printf "==> [1/6] loading xpatch (compiler -> ~a emit mode)~n" chez-machine)
+      (load xpatch))
+    (printf "==> [1/6] host already emits ~a; xpatch not needed~n" chez-machine))
 (library-directories
   (map (lambda (pair)
          (cons (if (pair? pair) (car pair) pair) obj-dir))
@@ -275,7 +280,7 @@
 
 ;; ── Stage 2: compile-program main-binary.ss ────────────────────────────────
 (printf "==> [2/6] compile-program ~a -> ~a~n" entry-script entry-so)
-(guard (e [#t (cleanup!) (raise e)])
+(guard (e [#t (raise e)])
   (compile-program entry-script entry-so))
 
 ;; ── Stage 3: compile-whole-program → wpo .so ───────────────────────────────
@@ -366,8 +371,11 @@
     "jerboa_wasm_fuel_remaining" "jerboa_wasm_get_log"
     "jerboa_wasm_allow_cdb_dir" "jerboa_wasm_set_socket"
     ;; jerboa-native (regex) — visit-time even if jcode never matches
-    "jerboa_regex_compile" "jerboa_regex_is_match"
-    "jerboa_regex_find" "jerboa_regex_replace_all" "jerboa_regex_free"
+    "jerboa_regex_compile" "jerboa_regex_compile_ex" "jerboa_regex_is_match"
+    "jerboa_regex_find" "jerboa_regex_find_at"
+    "jerboa_regex_captures" "jerboa_regex_group_count"
+    "jerboa_regex_replace_all" "jerboa_regex_replace_all_alloc"
+    "jerboa_regex_free"
     ;; jerboa-native (aproc) — (std os aproc) for bash tool
     "jerboa_aproc_spawn" "jerboa_aproc_spawn_pty"
     "jerboa_aproc_set_nonblock" "jerboa_aproc_killpg" "jerboa_aproc_wait4"
@@ -398,8 +406,9 @@
     "sysconf" "getpagesize" "getrlimit"
     "system" "getenv" "putenv" "_exit" "exit" "execvp" "execve"
     ;; files/directories/FIFOs — std/os/temp, std/os/posix
-    "access" "chdir" "stat" "fstat" "lstat" "readlink" "realpath"
-    "mkdir" "fdopen"
+    "access" "chdir" "chmod" "fchmod" "fsync"
+    "stat" "fstat" "lstat" "readlink" "realpath"
+    "mkdir" "mkdirat" "openat" "unlinkat" "renameat" "linkat" "fdopen"
     "mkstemp" "mkdtemp" "mkfifo" "umask" "unlink" "rmdir"
     ;; errno location + Linux sandboxing
     "__errno_location" "fcntl" "prctl" "syscall"))
diff --git a/src/jcode/core/path-policy.ss b/src/jcode/core/path-policy.ss
index 67c826d..cf1eba6 100644
--- a/src/jcode/core/path-policy.ss
+++ b/src/jcode/core/path-policy.ss
@@ -180,15 +180,16 @@
       (lambda ()
         ;; Older bundled Jerboa releases used Linux struct-stat offsets on
         ;; Darwin. Keep the fd allocation/error handling from posix-fstat but
-        ;; decode the stable leading fields locally on Darwin.
+        ;; decode the stable leading fields locally on Darwin. Current Jerboa
+        ;; returns the stat storage as a bytevector, not a raw foreign pointer.
         (let* ((dev (if (darwin-machine?)
-                      (foreign-ref 'unsigned-32 st 0)
+                      (bytevector-u32-native-ref st 0)
                       (stat-dev st)))
                (mode (if (darwin-machine?)
-                       (foreign-ref 'unsigned-16 st 4)
+                       (bytevector-u16-native-ref st 4)
                        (stat-mode st)))
                (nlink (if (darwin-machine?)
-                        (foreign-ref 'unsigned-16 st 6)
+                        (bytevector-u16-native-ref st 6)
                         (stat-nlink st)))
                (kind (bitwise-and mode #o170000)))
           (values dev mode nlink
diff --git a/src/jcode/ui/cli.ss b/src/jcode/ui/cli.ss
index 6d08a1d..8c5c0d9 100644
--- a/src/jcode/ui/cli.ss
+++ b/src/jcode/ui/cli.ss
@@ -1379,15 +1379,12 @@ EXAMPLES:
 
 (def (save-terminal-state)
   (guard (e [else #f])
-    ;; P3.1: Use argv-style spawn instead of shell string to avoid injection
-    (let-values (((to-stdin from-stdout from-stderr pid)
-                  (open-process-ports "stty" '("-g")
-                    (buffer-mode block) (native-transcoder))))
-      (let ((state (get-line from-stdout)))
-        (close-port to-stdin)
-        (close-port from-stdout)
-        (close-port from-stderr)
-        (if (eof-object? state) #f state)))))
+    ;; Use argv-style spawn so the command is never interpreted by a shell.
+    (let-values (((stdout stderr status)
+                  (aproc-run/status* '("stty" "-g"))))
+      (and (= status 0)
+           (string? stdout)
+           (string-trim stdout)))))
 
 (def (restore-terminal-state! state)
   (when (and state (string? state) (> (string-length state) 0))
diff --git a/vendor-lock.env b/vendor-lock.env
index 5603681..0d904b5 100644
--- a/vendor-lock.env
+++ b/vendor-lock.env
@@ -4,7 +4,7 @@ TERMBOX2_COMMIT=605398fa79108412976191e062ea14bd4bd30213 # gitsafe:ignore immuta
 TERMBOX2_TREE=e3ff0f62611cb5cdc94bbea2bc0780541359a65e # gitsafe:ignore immutable Git tree id
 
 JERBOA_WEBSEARCH_REPOSITORY=https://git.jerboa.sh/ober/jerboa-websearch.git
-JERBOA_WEBSEARCH_COMMIT=9d1beae59f3f20c98283e7754e98a4b478c892e1 # gitsafe:ignore immutable Git object id
+JERBOA_WEBSEARCH_COMMIT=c0fa1ba67b53c256cbeda8446d7d0cf6116e18b2 # gitsafe:ignore immutable Git object id
 JERBOA_WEBSEARCH_TREE=ab1a143f3189e7be8e69a59dd4fca2d03f88d6d8 # gitsafe:ignore immutable Git tree id
 
 JERBOA_REPOSITORY=https://git.jerboa.sh/ober/jerboa.git