Fix static Qt Podman build

ober

11ac67ff9538b715e5d3622489f3b62280e25211

diff --git a/CLAUDE.md b/CLAUDE.md
index 2931d30..d4e07de 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -17,7 +17,7 @@ make build           # Translate src/*.ss → lib/*.sls (incremental)
 make rebuild         # Force full retranslation
 make run             # Build and run TUI editor
 make run-qt          # Build and run Qt editor
-make static-qt       # Build static jemacs-qt binary via Docker
+make static-qt       # Build static jemacs-qt binary via Podman
 ```
 
 ## MANDATORY: Build, Compile, and Verify After EVERY Change
@@ -27,14 +27,14 @@ make static-qt       # Build static jemacs-qt binary via Docker
 After ANY code change to `.ss` files, you MUST run these steps IN ORDER before responding to the user:
 
 1. `make build` — rebuild `.sls` files from `.ss` sources. Fix any errors before proceeding.
-2. `make static-qt` — rebuild the static Docker binary. Fix any errors before proceeding.
+2. `make static-qt` — rebuild the static Podman binary. Fix any errors before proceeding.
 3. `./jemacs-qt --version` — verify binary launches without exceptions.
 
 If ANY step fails, the fix is NOT done. Do NOT tell the user anything is fixed, working, or ready until all 3 steps pass. Do NOT skip step 2 or 3 — interpreted mode (`make run-qt`) does NOT prove the static binary works.
 
 Common pitfalls when step 3 fails:
 
-- **`library (std ...) not found`**: The Docker image has a stale jerboa `std/` tree. New modules must be added to the sync list in the `linux-static-qt-docker` Makefile target AND compiled into the WPO step in `build-binary-qt.ss`.
+- **`library (std ...) not found`**: The Podman image has a stale jerboa `std/` tree. New modules must be added to the sync list in the `linux-static-qt-podman` Makefile target AND compiled into the WPO step in `build-binary-qt.ss`.
 - **`Dynamic loading not supported`**: Any `load-shared-object` call must be guarded with the `JEMACS_STATIC` env var check (the binary sets `JEMACS_STATIC=1`).
 - **`final:` or other unsupported keywords**: jerbuild doesn't support all Gerbil `defstruct` keywords — remove them.
 - **Vendored dependencies**: run `make vendor-deps` and use `vendor/chez-*` plus `vendor/jerboa-*` checkouts. Do not rely on developer-local dependency paths or `gerbil-*` shim repos. The Qt shim sources live in this repo's `vendor/` directory.
diff --git a/Dockerfile b/Dockerfile
index b4b146e..26e093b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,13 +1,13 @@
-# Intermediate Docker image for jemacs-qt static builds.
+# Intermediate Podman image for jemacs-qt static builds.
 # Bakes static Qt6 + QScintilla from source, plus all Chez Scheme
 # dependencies (jerboa, gherkin, jsh, chez-pcre2, chez-scintilla,
 # chez-qt) so that subsequent jemacs-qt builds only compile jemacs
 # itself (~5-10 min instead of ~30 min).
 #
 # Build with:
-#   make docker-deps
+#   make podman-deps
 #
-# Uses BuildKit --build-context to pull dependency sources without
+# Uses Podman --build-context to pull dependency sources without
 # copying them into the project directory.
 
 ARG ARCH=x86_64
@@ -272,40 +272,11 @@ COPY vendor/qt_chez_shim.c vendor/qt_shim.h /deps/chez-qt/
 # Pre-compile all Chez library dependencies.
 # These .so files are baked into the image so jemacs builds only
 # need to compile jemacs-specific modules.
+COPY support/static-precompile-deps.ss /tmp/static-precompile-deps.ss
 RUN /opt/chez/bin/scheme \
       --libdirs /deps/jerboa/lib:/deps/gherkin:/deps/jsh/src:/deps/chez-pcre2:/deps/chez-scintilla/src:/deps/chez-qt \
       --compile-imported-libraries \
-      --script /dev/stdin <<'EOF'
-#!chezscheme
-(import
-  (except (chezscheme) make-hash-table hash-table? iota 1+ 1-
-          getenv path-extension path-absolute? thread?
-          make-mutex mutex? mutex-name)
-  (jerboa core)
-  (jerboa runtime)
-  (std sugar)
-  (std format)
-  (std sort)
-  (std pregexp)
-  (std foreign)
-  (std misc list)
-  (std misc thread)
-  (std os path)
-  (std os signal)
-  (compat types)
-  (compat gambit-compat)
-  (runtime util)
-  (runtime table)
-  (runtime c3)
-  (runtime mop)
-  (compat gambit)
-  (jsh ffi)
-  (jsh static-compat)
-  (chez-scintilla constants)
-  (chez-qt ffi)
-  (chez-qt qt))
-(display "Chez deps pre-compiled OK\n")
-EOF
+      --script /tmp/static-precompile-deps.ss
 
 # Build static pcre2 shim object
 RUN PCRE2_CFLAGS=$(pkg-config --cflags libpcre2-8 2>/dev/null || echo "") && \
diff --git a/Dockerfile.qt b/Dockerfile.qt
index 4b48db6..f3173fd 100644
--- a/Dockerfile.qt
+++ b/Dockerfile.qt
@@ -1,4 +1,4 @@
-# Dockerfile.qt — Build jemacs-qt static binary using jerboa21/jerboa + Qt6
+# Podman-compatible container recipe for building static jemacs-qt with Qt6.
 #
 # Multi-stage build:
 #   Stage 1 (Alpine):          Build Qt6 static, QScintilla, tree-sitter, libvterm (musl)
@@ -6,9 +6,9 @@
 #   Stage 2 (jerboa21/jerboa): Copy Qt artifacts + Jerboa deps, build jemacs-qt
 #
 # Usage:
-#   docker build -f Dockerfile.qt -t jemacs-qt-builder .
-#   id=$(docker create jemacs-qt-builder)
-#   docker cp $id:/out/jemacs-qt ./jemacs-qt && docker rm $id
+#   podman build -f Dockerfile.qt -t jemacs-qt-builder .
+#   id=$(podman create jemacs-qt-builder)
+#   podman cp $id:/out/jemacs-qt ./jemacs-qt && podman rm $id
 #   chmod +x jemacs-qt
 
 # ── Stage 1: Build Qt6 + QScintilla + tree-sitter + libvterm on Alpine ───────
diff --git a/Dockerfile.tui b/Dockerfile.tui
index a74914d..72c0a8c 100644
--- a/Dockerfile.tui
+++ b/Dockerfile.tui
@@ -1,11 +1,11 @@
-# Dockerfile.tui — Build jemacs (TUI) static binary using jerboa21/jerboa
+# Podman-compatible container recipe for building static jemacs (TUI).
 #
 # Produces a fully static jemacs binary with zero runtime dependencies.
 #
 # Usage:
-#   docker build -f Dockerfile.tui -t jemacs-tui-builder .
-#   id=$(docker create jemacs-tui-builder)
-#   docker cp $id:/out/jemacs ./jemacs && docker rm $id
+#   podman build -f Dockerfile.tui -t jemacs-tui-builder .
+#   id=$(podman create jemacs-tui-builder)
+#   podman cp $id:/out/jemacs ./jemacs && podman rm $id
 #   chmod +x jemacs
 
 FROM jerboa21/jerboa AS builder
diff --git a/Makefile b/Makefile
index 03cff37..1008228 100644
--- a/Makefile
+++ b/Makefile
@@ -80,7 +80,8 @@ endif
         test-org-lint test-org-num test-org-property test-org-src test-org-tempo \
         test-vtscreen test-debug-repl test-qt test-qt-e2e build-qt binary-qt \
         test-pty test-emacs test-functional test-term-hang \
-        docker-deps static-qt static-tui clean-docker check-root \
+        podman-deps ensure-podman-deps static-qt static-tui clean-podman check-podman check-root \
+        linux-static-qt-podman linux-static-tui-podman \
         build-jemacs-qt-static build-jemacs-tui-static binary macos \
         linux-tui linux-tui-local \
         linux-qt linux-qt-local \
@@ -96,8 +97,8 @@ all:
 	@echo "  run            Build and run TUI editor"
 	@echo "  run-qt         Build and run Qt editor"
 	@echo "  binary         Build TUI binary (./jemacs) — embeds Scheme, links system libs"
-	@echo "  static-tui     Build fully static TUI binary via Docker (./jemacs)"
-	@echo "  static-qt      Build static jemacs-qt binary via Docker"
+	@echo "  static-tui     Build fully static TUI binary via Podman (./jemacs)"
+	@echo "  static-qt      Build static jemacs-qt binary via Podman"
 	@echo "  macos          Build native jemacs-qt binary for macOS"
 	@echo "  test           Full test suite (all tiers + org)"
 	@echo "  test-functional  250 dispatch-chain integration tests"
@@ -472,17 +473,22 @@ binary: build vterm_shim.$(SHLIB_EXT) chez_scintilla_shim.$(SHLIB_EXT) pcre2_shi
 	$(SCHEME) $(LIBDIRS) --script build-binary.ss
 
 # =============================================================================
-# Static binary builds (Docker-based, Alpine musl)
+# Static binary builds (Podman-based, Alpine musl)
 # =============================================================================
 
 ARCH    := $(shell uname -m)
 UID     := $(shell id -u)
 GID     := $(shell id -g)
+PODMAN  ?= podman
+PODMAN_PLATFORM ?= linux/amd64
+PODMAN_BUILD_FLAGS ?=
+PODMAN_RUN_FLAGS ?=
 
 # Dependency source directories (vendored clones)
 JERBOA_SRC   ?= $(JERBOA)
 GHERKIN_SRC  ?= $(CURDIR)/vendor/gherkin-runtime
 JSH_SRC      ?= $(JSH_ROOT)
+JSH_VENDOR_SRC ?= $(JSH_SRC)/vendor
 PCRE2_SRC    ?= $(CHEZ_PCRE2_ROOT)
 SCI_SRC      ?= $(CHEZ_SCINTILLA_ROOT)
 QT_SRC       ?= $(CQT)
@@ -495,12 +501,16 @@ JSH_COREUTILS_LIB ?= $(shell test -f $(_RUST_COREUTILS) && echo $(_RUST_COREUTIL
 
 DEPS_IMAGE := jemacs-deps:$(ARCH)
 
-# Build intermediate deps Docker image (run once, or when deps change).
+check-podman:
+	@command -v $(PODMAN) >/dev/null 2>&1 || \
+	  { echo "ERROR: Podman executable '$(PODMAN)' not found. Install Podman or set PODMAN=/path/to/podman."; exit 1; }
+
+# Build intermediate deps Podman image (run once, or when deps change).
 # Takes ~45-60 min: Qt6 static + QScintilla + Chez Scheme + all shims.
 CHEZ_COMMIT ?= 902a10098603481afce0ec8588114234c09d6318
 
-docker-deps:
-	DOCKER_BUILDKIT=1 docker build \
+podman-deps: check-podman
+	$(PODMAN) build $(PODMAN_BUILD_FLAGS) \
 	  --build-arg ARCH=$(ARCH) \
 	  --build-arg CHEZ_COMMIT=$(CHEZ_COMMIT) \
 	  --build-context jerboa-src=$(JERBOA_SRC) \
@@ -515,19 +525,23 @@ docker-deps:
 	  -t $(DEPS_IMAGE) \
 	  $(CURDIR)
 
-# Fast static Qt binary via Docker (requires deps image from `make docker-deps`).
+ensure-podman-deps: check-podman
+	@$(PODMAN) image exists $(DEPS_IMAGE) || \
+	  { echo "Deps image '$(DEPS_IMAGE)' not found; building with 'make podman-deps'."; $(MAKE) podman-deps; }
+
+# Fast static Qt binary via Podman.
 # Builds only jemacs-qt itself (~5-10 min). Output: ./jemacs-qt (static ELF).
-static-qt: linux-static-qt-docker
+static-qt: linux-static-qt-podman
 
-clean-docker:
-	-docker run --rm -v $(CURDIR):/src:z alpine sh -c "rm -rf /src/jemacs-qt /src/jemacs-qt.boot /src/qt-main.so /src/qt-main.wpo /src/jemacs-qt-all.so 2>/dev/null; true"
+clean-podman: check-podman
+	-$(PODMAN) run --rm $(PODMAN_RUN_FLAGS) -v $(CURDIR):/src:z alpine sh -c "rm -rf /src/jemacs-qt /src/jemacs-qt.boot /src/qt-main.so /src/qt-main.wpo /src/jemacs-qt-all.so 2>/dev/null; true"
 
 check-root:
 	@if [ "$$(id -u)" = "0" ]; then \
 	  git config --global --add safe.directory '*'; \
 	fi
 
-# In-container build target (called by linux-static-qt-docker)
+# In-container build target (called by linux-static-qt-podman)
 # Chez machine type on Alpine x86_64 is ta6le (same as glibc Linux).
 # Auto-detect the versioned csv* subdirectory (e.g. csv10.4.0-pre-release.3/ta6le).
 CHEZ_MT ?= ta6le
@@ -538,7 +552,11 @@ build-jemacs-qt-static: check-root
 	cp /src/vendor/jerboa-shell/embed-crypto.c /deps/jsh/ 2>/dev/null; \
 	cp /src/vendor/jerboa-shell/embed-crypto.h /deps/jsh/ 2>/dev/null; \
 	cp /src/vendor/jerboa-shell/ffi-shim.c /deps/jsh/ 2>/dev/null; \
-	cp /src/vendor/jerboa-shell/libcoreutils.c /deps/jsh/ 2>/dev/null; \
+	if [ -f /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c ]; then \
+	  cp /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c /deps/jsh/libcoreutils.c; \
+	elif [ -f /src/vendor/jerboa-shell/patches/libcoreutils.c ]; then \
+	  cp /src/vendor/jerboa-shell/patches/libcoreutils.c /deps/jsh/libcoreutils.c; \
+	fi; \
 	if [ -f /src/vendor/jerboa-shell/crypto_stub.c ]; then \
 	  gcc -c -O2 /src/vendor/jerboa-shell/crypto_stub.c -o /tmp/jemacs-build/crypto_stub.o; \
 	fi; \
@@ -564,16 +582,13 @@ build-jemacs-qt-static: check-root
 	find /deps/chez-qt -name '*.wpo' -delete && \
 	/opt/chez/bin/scheme --libdirs /deps/chez-qt \
 	  --compile-imported-libraries --script /deps/chez-qt/compile-libs.ss && \
-	rm -f /deps/chez-qt/chez-qt/*.wpo && \
-	cp /src/vendor/chez-pcre2-ffi-static.ss /deps/chez-pcre2/chez-pcre2/ffi.ss && \
-	/opt/chez/bin/scheme --libdirs /deps/chez-pcre2 \
-	  --compile-imported-libraries --script /src/vendor/chez-pcre2-compile-libs.ss && \
-	rm -f /deps/chez-pcre2/chez-pcre2/*.wpo && \
-	cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \
-	  --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \
-	rm -f /deps/chez-scintilla/src/chez-scintilla/*.wpo && \
-	cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \
+		cp /src/vendor/chez-pcre2-ffi-static.ss /deps/chez-pcre2/chez-pcre2/ffi.ss && \
+		/opt/chez/bin/scheme --libdirs /deps/chez-pcre2 \
+		  --compile-imported-libraries --script /src/vendor/chez-pcre2-compile-libs.ss && \
+		cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \
+		  --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \
+		cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \
 	cp /src/vendor/jerboa-net-tcp-raw-static.sls /deps/jerboa/lib/std/net/tcp-raw.sls && \
 	cp /src/vendor/jerboa-net-uri.sls /deps/jerboa/lib/std/net/uri.sls && \
 	rm -f /deps/jerboa/lib/std/net/*.wpo /deps/jerboa/lib/std/net/*.so && \
@@ -586,21 +601,19 @@ build-jemacs-qt-static: check-root
 	rm -f /deps/jerboa/lib/std/os/landlock.wpo /deps/jerboa/lib/std/os/landlock.so && \
 	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
 	  --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp.ss && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \
-	/opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \
-	rm -f /deps/jerboa/lib/std/net/*.wpo && \
-	cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \
+		/opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \
+		cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \
 	rm -f /deps/jerboa/lib/std/repl.wpo /deps/jerboa/lib/std/repl.so && \
-	cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \
-	rm -f /deps/jerboa/lib/std/repl.wpo && cd /src && \
-	rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \
-	rm -f /src/lib/jerboa/*.wpo && \
-	echo "Building tree-sitter shim + queries..." && \
+		cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \
+		cd /src && \
+		rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \
+		echo "Building tree-sitter shim + queries..." && \
 	gcc -c -O2 -I/opt/tree-sitter-include -o /tmp/jemacs-build/treesitter_shim.o \
 	    /src/support/treesitter_shim.c -Wall && \
 	gcc -c -O2 -o /tmp/jemacs-build/treesitter_queries.o \
@@ -610,19 +623,16 @@ build-jemacs-qt-static: check-root
 	find /deps/chez-ssl -name '*.so' -delete && find /deps/chez-ssl -name '*.wpo' -delete && \
 	find /deps/chez-https -name '*.so' -delete && find /deps/chez-https -name '*.wpo' -delete && \
 	find /deps/jerboa-aws -name '*.so' -delete && find /deps/jerboa-aws -name '*.wpo' -delete && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme \
-	  --libdirs /deps/chez-ssl/src:/deps/jerboa/lib \
-	  --compile-imported-libraries -q --script /src/vendor/chez-ssl-compile-libs.ss && \
-	find /deps/chez-ssl -name '*.wpo' -delete && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme \
-	  --libdirs /deps/chez-https/src:/deps/chez-ssl/src \
-	  --compile-imported-libraries -q --script /src/vendor/chez-https-compile-libs.ss && \
-	find /deps/chez-https -name '*.wpo' -delete && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme \
-	  --libdirs /deps/jerboa-aws:/deps/chez-https/src:/deps/chez-ssl/src:/deps/jerboa/lib \
-	  --compile-imported-libraries -q --script /src/vendor/jerboa-aws-compile-libs.ss && \
-	find /deps/jerboa-aws -name '*.wpo' -delete && \
-	JEMACS_STATIC=1 \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme \
+		  --libdirs /deps/chez-ssl/src:/deps/jerboa/lib \
+		  --compile-imported-libraries -q --script /src/vendor/chez-ssl-compile-libs.ss && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme \
+		  --libdirs /deps/chez-https/src:/deps/chez-ssl/src \
+		  --compile-imported-libraries -q --script /src/vendor/chez-https-compile-libs.ss && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme \
+		  --libdirs /deps/jerboa-aws:/deps/chez-https/src:/deps/chez-ssl/src:/deps/jerboa/lib \
+		  --compile-imported-libraries -q --script /src/vendor/jerboa-aws-compile-libs.ss && \
+		JEMACS_STATIC=1 \
 	CHEZ_DIR=$(CHEZ_MUSL_DIR) \
 	JERBOA_DIR=/deps/jerboa/lib \
 	JSH_DIR=/deps/jsh/src \
@@ -645,15 +655,14 @@ build-jemacs-qt-static: check-root
 	  --libdirs lib:/deps/jerboa/lib:/deps/jsh/src:/deps/jsh/vendor/jerboa-coreutils/lib:/deps/jsh/vendor/jerboa-awk/lib:/deps/jsh/vendor/jerboa-sed/lib:/deps/jsh/vendor/chez-ssh/src:/deps/jsh/vendor/chez-sqlite/src:/deps/jsh/vendor/chez-crypto/src:/deps/jsh/vendor/chez-fuse/lib:/src/vendor/gherkin-runtime:/deps/chez-pcre2:/deps/chez-scintilla/src:/deps/chez-qt:/deps/jerboa-aws:/deps/chez-ssl/src:/deps/chez-https/src \
 	  --script build-binary-qt.ss
 
-linux-static-qt-docker:
-	@docker image inspect $(DEPS_IMAGE) >/dev/null 2>&1 || \
-	  { echo "ERROR: Deps image '$(DEPS_IMAGE)' not found. Run 'make docker-deps' first."; exit 1; }
-	docker run --rm \
+linux-static-qt-podman: ensure-podman-deps
+	$(PODMAN) run --rm $(PODMAN_RUN_FLAGS) \
 	  --ulimit nofile=8192:8192 \
 	  -v $(CURDIR):/src:z \
 	  -v $(JERBOA)/lib/std:/host-jerboa-std:ro \
 	  -v $(JERBOA)/lib/jerboa:/host-jerboa-core:ro \
 	  -v $(JSH_SRC)/src:/host-jsh-src:ro \
+	  -v $(JSH_VENDOR_SRC):/host-jsh-vendor:ro \
 	  -v $(JSH_COREUTILS_LIB):/host-jsh-coreutils.a:ro \
 	  -v $(JAWS_SRC):/host-jaws:ro \
 	  -v $(CSSL_SRC):/host-chez-ssl:ro \
@@ -670,30 +679,28 @@ linux-static-qt-docker:
 	         fi; \
 	         cp /host-jsh-coreutils.a /deps/jsh/libjsh_coreutils.a; \
 	         cp -a /host-jsh-src/. /deps/jsh/src/; \
+	         mkdir -p /deps/jsh/vendor && cp -a /host-jsh-vendor/. /deps/jsh/vendor/; \
 	         echo 'SYNC: bulk-copying host jerboa std/ and jerboa/ into container...'; \
 	         cp -a /host-jerboa-std/. /deps/jerboa/lib/std/ && \
 	         cp -a /host-jerboa-core/. /deps/jerboa/lib/jerboa/ && \
 	         find /deps/jerboa/lib -name '*.so' -delete && \
 	         find /deps/jerboa/lib -name '*.wpo' -delete && \
-	         echo '(import (chezscheme)) (compile-imported-libraries #t) (import (jerboa core)) (import (jerboa prelude))' \
+	         echo '(import (chezscheme)) (compile-imported-libraries #t) (generate-wpo-files #t) (import (jerboa core)) (import (jerboa prelude))' \
 	           > /tmp/compile-jerboa-core.ss && \
 	         cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
 	           -q --script /tmp/compile-jerboa-core.ss && \
-	         rm -f /deps/jerboa/lib/jerboa/*.wpo && \
 	         echo 'COMPILED: jerboa core + prelude'; \
 	         mkdir -p /deps/jerboa-aws /deps/chez-ssl/src /deps/chez-https/src && \
 	         cp -a /host-jaws/. /deps/jerboa-aws/ && \
 	         cp -a /host-chez-ssl/. /deps/chez-ssl/ && \
 	         cp -a /host-chez-https/. /deps/chez-https/ && \
 	         echo 'SYNC: jerboa-aws, chez-ssl, chez-https copied'; \
-	         chmod 755 /root && \
-	         chown -R $(UID):$(GID) /opt/ /deps && \
-	         mkdir -p /tmp/jemacs-build && chown $(UID):$(GID) /tmp/jemacs-build && \
-	         exec su-exec $(UID):$(GID) env HOME=/tmp/jemacs-build sh -c '\
+	         mkdir -p /tmp/jemacs-build && \
+	         exec env HOME=/tmp/jemacs-build sh -c '\
 	           cd /src && make build-jemacs-qt-static'"
 
 # =============================================================================
-# Static TUI binary (Docker-based, Alpine musl)
+# Static TUI binary (Podman-based, Alpine musl)
 # =============================================================================
 
 # Scintilla/termbox/Lexilla C/C++ source + headers used to build static
@@ -701,29 +708,31 @@ linux-static-qt-docker:
 # vendored checkout.
 SCI_VENDOR_SRC ?= $(CHEZ_SCINTILLA_ROOT)/vendor
 
-# Fast static TUI binary via Docker (requires deps image from `make docker-deps`).
+# Fast static TUI binary via Podman.
 # Builds Scintilla+termbox+Lexilla from source, then ./jemacs (~5-10 min).
-static-tui: linux-static-tui-docker
+static-tui: linux-static-tui-podman
 
-# In-container build target for TUI static binary (called by linux-static-tui-docker)
+# In-container build target for TUI static binary (called by linux-static-tui-podman)
 build-jemacs-tui-static: check-root
 	rm -f /src/src/.jerbuild-hashes; \
 	cp /src/vendor/jerboa-shell/embed-crypto.c /deps/jsh/ 2>/dev/null; \
 	cp /src/vendor/jerboa-shell/embed-crypto.h /deps/jsh/ 2>/dev/null; \
 	cp /src/vendor/jerboa-shell/ffi-shim.c /deps/jsh/ 2>/dev/null; \
-	cp /src/vendor/jerboa-shell/libcoreutils.c /deps/jsh/ 2>/dev/null; \
+	if [ -f /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c ]; then \
+	  cp /src/vendor/jerboa-shell/vendor/jerboa-coreutils/support/libcoreutils.c /deps/jsh/libcoreutils.c; \
+	elif [ -f /src/vendor/jerboa-shell/patches/libcoreutils.c ]; then \
+	  cp /src/vendor/jerboa-shell/patches/libcoreutils.c /deps/jsh/libcoreutils.c; \
+	fi; \
 	cd /src && find lib -name '*.so' -o -name '*.wpo' | xargs rm -f 2>/dev/null; \
 	find /src/src/jerboa-emacs -name '*.ss' | sed 's|/src/src/|/src/lib/|; s|\.ss$$|.sls|' | xargs rm -f 2>/dev/null; \
 	cd /src && make build SCHEME=/opt/chez/bin/scheme JERBOA=/deps/jerboa && \
 	cp /src/vendor/chez-pcre2-ffi-static.ss /deps/chez-pcre2/chez-pcre2/ffi.ss && \
 	/opt/chez/bin/scheme --libdirs /deps/chez-pcre2 \
 	  --compile-imported-libraries --script /src/vendor/chez-pcre2-compile-libs.ss && \
-	rm -f /deps/chez-pcre2/chez-pcre2/*.wpo && \
-	cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \
-	  --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \
-	rm -f /deps/chez-scintilla/src/chez-scintilla/*.wpo && \
-	cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \
+		cp /src/vendor/chez-scintilla-ffi-static.sls /deps/chez-scintilla/src/chez-scintilla/ffi.sls && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/chez-scintilla/src \
+		  --compile-imported-libraries --script /src/vendor/chez-scintilla-compile-libs.ss && \
+		cp /src/vendor/jerboa-net-tcp-static.sls /deps/jerboa/lib/std/net/tcp.sls && \
 	cp /src/vendor/jerboa-net-tcp-raw-static.sls /deps/jerboa/lib/std/net/tcp-raw.sls && \
 	cp /src/vendor/jerboa-net-uri.sls /deps/jerboa/lib/std/net/uri.sls && \
 	rm -f /deps/jerboa/lib/std/net/*.wpo /deps/jerboa/lib/std/net/*.so && \
@@ -736,21 +745,19 @@ build-jemacs-tui-static: check-root
 	rm -f /deps/jerboa/lib/std/os/landlock.wpo /deps/jerboa/lib/std/os/landlock.so && \
 	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
 	  --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp.ss && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \
-	/opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \
-	rm -f /deps/jerboa/lib/std/net/*.wpo && \
-	cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-tcp-raw.ss && \
+		/opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-uri.ss && \
+		cp /src/vendor/jerboa-repl-static.sls /deps/jerboa/lib/std/repl.sls && \
 	rm -f /deps/jerboa/lib/std/repl.wpo /deps/jerboa/lib/std/repl.so && \
-	cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \
-	rm -f /deps/jerboa/lib/std/repl.wpo && cd /src && \
-	rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \
-	JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \
-	  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \
-	rm -f /src/lib/jerboa/*.wpo && \
-	echo "Building Scintilla+termbox+Lexilla static archives from source..." && \
+		cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl.ss && \
+		cd /src && \
+		rm -f /src/lib/jerboa/*.wpo /src/lib/jerboa/*.so && \
+		JEMACS_STATIC=1 /opt/chez/bin/scheme --libdirs /src/lib \
+		  --compile-imported-libraries --script /src/vendor/jerboa-compile-repl-socket.ss && \
+		echo "Building Scintilla+termbox+Lexilla static archives from source..." && \
 	make -C /deps/sci-vendor/scintilla/termbox/termbox_next && \
 	make -C /deps/sci-vendor/scintilla/termbox && \
 	make -C /deps/sci-vendor/lexilla/src && \
@@ -767,42 +774,39 @@ build-jemacs-tui-static: check-root
 	  --libdirs lib:/deps/jerboa/lib:/deps/jsh/src:/deps/jsh/vendor/jerboa-coreutils/lib:/deps/jsh/vendor/jerboa-awk/lib:/deps/jsh/vendor/jerboa-sed/lib:/deps/jsh/vendor/chez-ssh/src:/deps/jsh/vendor/chez-sqlite/src:/deps/jsh/vendor/chez-crypto/src:/deps/jsh/vendor/chez-fuse/lib:/src/vendor/gherkin-runtime:/deps/chez-pcre2:/deps/chez-scintilla/src \
 	  --script build-binary.ss
 
-linux-static-tui-docker:
-	@docker image inspect $(DEPS_IMAGE) >/dev/null 2>&1 || \
-	  { echo "ERROR: Deps image '$(DEPS_IMAGE)' not found. Run 'make docker-deps' first."; exit 1; }
+linux-static-tui-podman: ensure-podman-deps
 	@test -d $(SCI_VENDOR_SRC) || \
 	  { echo "ERROR: SCI_VENDOR_SRC='$(SCI_VENDOR_SRC)' not found. Populate it from the chez-scintilla dependency or set SCI_VENDOR_SRC."; exit 1; }
-	docker run --rm \
+	$(PODMAN) run --rm $(PODMAN_RUN_FLAGS) \
 	  --ulimit nofile=8192:8192 \
 	  -v $(CURDIR):/src:z \
 	  -v $(SCI_VENDOR_SRC):/deps/sci-vendor:ro \
 	  -v $(JERBOA)/lib/std:/host-jerboa-std:ro \
 	  -v $(JERBOA)/lib/jerboa:/host-jerboa-core:ro \
 	  -v $(JSH_SRC)/src:/host-jsh-src:ro \
+	  -v $(JSH_VENDOR_SRC):/host-jsh-vendor:ro \
 	  -v $(JSH_COREUTILS_LIB):/host-jsh-coreutils.a:ro \
 	  $(DEPS_IMAGE) \
 	  sh -c "apk add --no-cache libvterm-dev libvterm-static; \
 	         cp /host-jsh-coreutils.a /deps/jsh/libjsh_coreutils.a; \
 	         cp -a /host-jsh-src/. /deps/jsh/src/; \
+	         mkdir -p /deps/jsh/vendor && cp -a /host-jsh-vendor/. /deps/jsh/vendor/; \
 	         echo 'SYNC: bulk-copying host jerboa std/ and jerboa/ into container...'; \
 	         cp -a /host-jerboa-std/. /deps/jerboa/lib/std/ && \
 	         cp -a /host-jerboa-core/. /deps/jerboa/lib/jerboa/ && \
 	         find /deps/jerboa/lib -name '*.so' -delete && \
 	         find /deps/jerboa/lib -name '*.wpo' -delete && \
-	         echo '(import (chezscheme)) (compile-imported-libraries #t) (import (jerboa core)) (import (jerboa prelude))' \
+	         echo '(import (chezscheme)) (compile-imported-libraries #t) (generate-wpo-files #t) (import (jerboa core)) (import (jerboa prelude))' \
 	           > /tmp/compile-jerboa-core.ss && \
 	         cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
 	           -q --script /tmp/compile-jerboa-core.ss && \
-	         rm -f /deps/jerboa/lib/jerboa/*.wpo && \
 	         echo 'COMPILED: jerboa core + prelude'; \
-	         chmod 755 /root && \
-	         chown -R $(UID):$(GID) /opt/ /deps && \
-	         mkdir -p /tmp/jemacs-build && chown $(UID):$(GID) /tmp/jemacs-build && \
-	         exec su-exec $(UID):$(GID) env HOME=/tmp/jemacs-build sh -c '\
+	         mkdir -p /tmp/jemacs-build && \
+	         exec env HOME=/tmp/jemacs-build sh -c '\
 	           cd /src && make build-jemacs-tui-static'"
 
 # =============================================================================
-# Static TUI via jerboa21/jerboa Docker image (like jerboa-gitsafe)
+# Static TUI via jerboa21/jerboa Podman image (like jerboa-gitsafe)
 # =============================================================================
 
 JERBOA_IMAGE ?= jerboa21/jerboa
@@ -816,13 +820,13 @@ MUSL_JSH_ROOT ?= $(MUSL_DEPS)/jerboa-shell
 MUSL_JSH ?= $(MUSL_JSH_ROOT)/src
 MUSL_SCI_VENDOR ?= /build/sci-vendor
 
-# Docker build: produces ./jemacs static binary
-linux-tui:
-	@echo "=== Building jemacs static TUI binary in Docker ==="
-	docker build --platform linux/amd64 -f Dockerfile.tui -t jemacs-tui-builder .
-	@id=$$(docker create --platform linux/amd64 jemacs-tui-builder) && \
-	docker cp $$id:/out/jemacs ./jemacs && \
-	docker rm $$id >/dev/null
+# Podman build: produces ./jemacs static binary
+linux-tui: check-podman
+	@echo "=== Building jemacs static TUI binary in Podman ==="
+	$(PODMAN) build $(PODMAN_BUILD_FLAGS) --platform $(PODMAN_PLATFORM) -f Dockerfile.tui -t jemacs-tui-builder .
+	@id=$$($(PODMAN) create jemacs-tui-builder) && \
+	$(PODMAN) cp $$id:/out/jemacs ./jemacs && \
+	$(PODMAN) rm $$id >/dev/null
 	@chmod +x jemacs
 	@echo ""
 	@ls -lh jemacs
@@ -903,22 +907,22 @@ linux-tui-local: vendor-deps
 	@file jemacs
 
 # =============================================================================
-# Static Qt binary via jerboa21/jerboa Docker image
+# Static Qt binary via jerboa21/jerboa Podman image
 # =============================================================================
 
-# Docker build: produces ./jemacs-qt static binary
-linux-qt:
-	@echo "=== Building jemacs-qt static binary in Docker ==="
-	docker build --platform linux/amd64 -f Dockerfile.qt -t jemacs-qt-builder .
-	@id=$$(docker create --platform linux/amd64 jemacs-qt-builder) && \
-	docker cp $$id:/out/jemacs-qt ./jemacs-qt && \
-	docker rm $$id >/dev/null
+# Podman build: produces ./jemacs-qt static binary
+linux-qt: check-podman
+	@echo "=== Building jemacs-qt static binary in Podman ==="
+	$(PODMAN) build $(PODMAN_BUILD_FLAGS) --platform $(PODMAN_PLATFORM) -f Dockerfile.qt -t jemacs-qt-builder .
+	@id=$$($(PODMAN) create jemacs-qt-builder) && \
+	$(PODMAN) cp $$id:/out/jemacs-qt ./jemacs-qt && \
+	$(PODMAN) rm $$id >/dev/null
 	@chmod +x jemacs-qt
 	@echo ""
 	@ls -lh jemacs-qt
 	@file jemacs-qt
 
-# In-container build target (called inside Dockerfile.qt → jerboa21/jerboa stage)
+# In-container build target (called inside the Podman Qt build container)
 # Qt6 static libs are at /opt/qt6-static (copied from Alpine stage).
 # Tree-sitter is at /opt/tree-sitter-* (copied from Alpine stage).
 # Pre-compiled libqt_shim.a is at /opt/qt-shim/ (Alpine-musl g++, ABI-compatible).
diff --git a/build-binary-qt.ss b/build-binary-qt.ss
index 238e8dc..46c6adf 100644
--- a/build-binary-qt.ss
+++ b/build-binary-qt.ss
@@ -162,214 +162,76 @@
 
 ;; --- Step 2: Whole-program optimization ---
 (printf "[2/7] Running whole-program optimization...~n")
+(define wpo-missing-libraries '())
 (let ((missing (compile-whole-program "qt-main.wpo" "jemacs-qt-all.so")))
+  (set! wpo-missing-libraries missing)
   (unless (null? missing)
     (printf "  WPO: ~a libraries not incorporated (missing .wpo):~n" (length missing))
     (for-each (lambda (lib) (printf "    ~a~n" lib)) missing)))
 
 ;; --- Step 3: Make libs-only boot file ---
 (printf "[3/7] Creating libs-only boot file...~n")
+(define (symbol-path parts)
+  (let loop ((rest parts) (acc ""))
+    (cond
+      ((null? rest) acc)
+      ((string=? acc "")
+       (loop (cdr rest) (symbol->string (car rest))))
+      (else
+       (loop (cdr rest) (string-append acc "/" (symbol->string (car rest))))))))
+
+(define (library-ref->so-path lib)
+  (and (pair? lib)
+       (let ((head (car lib))
+             (tail (cdr lib)))
+         (case head
+           ((std)
+            (format "~a/std/~a.so" jerboa-dir (symbol-path tail)))
+           ((jerboa)
+            (if (and (pair? tail) (eq? (car tail) 'repl-socket))
+                "lib/jerboa/repl-socket.so"
+                (format "~a/jerboa/~a.so" jerboa-dir (symbol-path tail))))
+           ((jsh)
+            (format "~a/jsh/~a.so" jsh-dir (symbol-path tail)))
+           ((compat)
+            (if (and (pair? tail) (eq? (car tail) 'gambit))
+                (format "~a/compat/gambit.so" jsh-dir)
+                (format "~a/compat/~a.so" gherkin-dir (symbol-path tail))))
+           ((runtime)
+            (format "~a/runtime/~a.so" gherkin-dir (symbol-path tail)))
+           ((chez-pcre2)
+            (format "~a/chez-pcre2/~a.so" pcre2-dir (symbol-path tail)))
+           ((chez-scintilla)
+            (format "~a/chez-scintilla/~a.so" sci-dir (symbol-path tail)))
+           ((chez-qt)
+            (format "~a/chez-qt/~a.so" qt-dir (symbol-path tail)))
+           ((chez-ssl)
+            (format "~a/src/chez-ssl.so" chez-ssl-dir))
+           ((chez-https)
+            (format "~a/chez-https.so" chez-https-dir))
+           ((jerboa-aws)
+            (format "~a/jerboa-aws/~a.so" jaws-dir (symbol-path tail)))
+           ((jerboa-emacs)
+            (format "lib/jerboa-emacs/~a.so" (symbol-path tail)))
+           (else #f)))))
+
+(define (wpo-missing-so-files)
+  (filter values (map library-ref->so-path wpo-missing-libraries)))
+
+(define (unique-strings strings)
+  (let loop ((rest strings) (seen '()) (acc '()))
+    (cond
+      ((null? rest) (reverse acc))
+      ((member (car rest) seen) (loop (cdr rest) seen acc))
+      (else (loop (cdr rest) (cons (car rest) seen) (cons (car rest) acc))))))
+
 (define (existing-so-files paths)
   (filter file-exists? paths))
-(apply make-boot-file "jemacs-qt.boot" '("scheme" "petite")
-  (existing-so-files
-  (append
-    ;; Jerboa runtime (no deps on other jerboa libs)
-    (map (lambda (m) (format "~a/~a.so" jerboa-dir m))
-      '("jerboa/runtime"))
-    ;; Jerboa stdlib
-    (map (lambda (m) (format "~a/~a.so" jerboa-dir m))
-      '("std/error"
-        "std/format"
-        "std/sort"
-        "std/pregexp"
-        "std/foreign"
-        "std/misc/string"
-        "std/misc/list"
-        "std/misc/alist"
-        "std/misc/thread"
-        "std/misc/fmt"
-        "std/os/path"
-        "std/os/signal"
-        "std/os/fdio"
-        "std/misc/custodian"
-        "std/misc/config"
-        "std/misc/memoize"
-        "std/misc/terminal"
-        "std/misc/trie"
-        "std/misc/lru-cache"
-        "std/misc/ports"
-        "std/srfi/srfi-13"
-        "std/text/json"
-        "std/actor/mpsc"
-        "std/actor/core"
-        "std/actor/transport"
-        "std/crypto/native"
-        "std/crypto/random"
-        "std/os/sandbox"
-        "std/os/landlock"
-        "std/security/capsicum"))
-    ;; Jerboa core + sugar + repl + dependencies
-    ;; std/typed: jerboa/core imports it
-    ;; std/result: std/sugar imports it
-    (map (lambda (m) (format "~a/~a.so" jerboa-dir m))
-      '("std/result"
-        "std/typed"
-        "jerboa/core"
-        "std/sugar"
-        "std/repl"))
-    ;; std/net/tcp and std/net/uri (compiled by step 1)
-    (map (lambda (m) (format "~a/~a.so" jerboa-dir m))
-      '("std/net/tcp"
-        "std/net/tcp-raw"
-        "std/net/uri"))
-    ;; jerboa/repl-socket (non-blocking socket FFI for debug REPL + IPC)
-    (list "lib/jerboa/repl-socket.so")
-    ;; Gherkin MOP modules (WPO-missing, must be in boot file)
-    (map (lambda (m) (format "~a/~a.so" gherkin-dir m))
-      '("compat/types"
-        "compat/gambit-compat"
-        "runtime/util"
-        "runtime/table"
-        "runtime/c3"
-        "runtime/mop"))
-    ;; compat/gambit lives in jsh (not gherkin)
-    (list (format "~a/compat/gambit.so" jsh-dir))
-    ;; jsh modules (WPO-missing, all needed transitively)
-    (map (lambda (m) (format "~a/jsh/~a.so" jsh-dir m))
-      '("embed"
-        "embed-data"
-        "ffi"
-        "static-compat"
-        "pregexp-compat"
-        "util"
-        "arithmetic"
-        "ast"
-        "environment"
-        "registry"
-        "functions"
-        "signals"
-        "glob"
-        "expander"
-        "lexer"
-        "parser"
-        "redirect"
-        "pipeline"
-        "jobs"
-        "builtins"
-        "executor"
-        "control"
-        "script"
-        "macros"
-        "completion"
-        "fuzzy"
-        "fzf"
-        "history"
-        "prompt"
-        "lineedit"
-        "startup"
-        "stage"
-        "recording-index"
-        "recorder"
-        "player"
-        "conditions"
-        "config"
-        "sandbox"
-        "lib"))
-    ;; chez-pcre2 (compiled by step 1)
-    (map (lambda (m) (format "~a/chez-pcre2/~a.so" pcre2-dir m))
-      '("ffi" "pcre2"))
-    ;; std/net/request (WPO-missing)
-    (list (format "~a/std/net/request.so" jerboa-dir))
-    ;; chez-ssl + chez-https (TLS for AWS API)
-    (list (format "~a/src/chez-ssl.so" chez-ssl-dir)
-          (format "~a/chez-https.so" chez-https-dir))
-    ;; jerboa-aws EC2 modules
-    (map (lambda (m) (format "~a/jerboa-aws/~a.so" jaws-dir m))
-      '("creds" "crypto" "xml" "json" "time" "uri" "sigv4" "request" "api"))
-    (map (lambda (m) (format "~a/jerboa-aws/ec2/~a.so" jaws-dir m))
-      '("xml" "params" "api" "instances"))
-    ;; chez-scintilla (all modules — WPO-missing)
-    (map (lambda (m) (format "~a/chez-scintilla/~a.so" sci-dir m))
-      '("ffi" "constants" "style" "lexer" "scintilla" "tui"))
-    ;; chez-qt
-    (map (lambda (m) (format "~a/chez-qt/~a.so" qt-dir m))
-      '("ffi" "qt"))
-    ;; jerboa-emacs shared modules (topological order)
-    (map (lambda (m) (format "lib/jerboa-emacs/~a.so" m))
-      '(;; Tier 0: no jerboa-emacs deps
-        "customize" "themes" "pregexp-compat" "macros"
-        "vtscreen" "pty" "ipc" "debug-repl" "snippets"
-        ;; Tier 1: face
-        "face"
-        ;; Tier 2: core
-        "core"
-        ;; Tier 3: base editor modules
-        "buffer" "echo" "keymap" "repl" "shell-history"
-        "subprocess" "gsh-subprocess" "async" "chat"
-        "highlight"
-        ;; Tier 4: window system
-        "window" "modeline" "persist"
-        ;; Tier 5: org + shell
-        "org-parse" "gsh-eshell" "eshell" "shell"
-        "org-export" "org-highlight" "org-list" "org-table"
-        "org-clock" "org-babel" "org-capture" "org-agenda"
-        ;; Tier 6: helm + terminal
-        "helm" "terminal"
-        "helm-sources" "helm-tui"
-        ;; Tier 7: helm commands + editor extras
-        "helm-commands" "editor-extra-helpers"
-        ;; Tier 8: editor core
-        "editor-core"
-        ;; Tier 9: editor UI
-        "editor-ui" "editor-text"
-        ;; Tier 10: advanced editor
-        "editor-advanced"
-        ;; Tier 11-13: editor commands
-        "editor-cmds-a" "editor-cmds-b" "editor-cmds-c"
-        ;; Tier 14+: editor extras chain
-        "editor-extra-ai"
-        "editor-extra-editing" "editor-extra-editing2"
-        "editor-extra-media" "editor-extra-media2"
-        "editor-extra-modes"
-        "editor-extra-org"
-        "editor-extra-regs" "editor-extra-regs2"
-        "editor-extra-tools" "editor-extra-tools2"
-        "editor-extra-vcs" "editor-extra-web"
-        "editor-extra-final" "editor-extra"
-        ;; TUI top-level (editor shared with Qt)
-        "editor"))
-    ;; Qt-specific modules
-    (map (lambda (m) (format "lib/jerboa-emacs/qt/~a.so" m))
-      '(;; Foundation
-        "sci-shim" "keymap"))
-    ;; treesitter must come before qt/buffer (which imports it)
-    (list "lib/jerboa-emacs/treesitter.so")
-    (map (lambda (m) (format "lib/jerboa-emacs/qt/~a.so" m))
-      '("buffer" "echo"
-        "image" "magit"
-        "highlight" "modeline" "window"
-        "lsp-client" "helm-qt"
-        "snippets" "menubar"
-        ;; Commands (pairs: base + extended)
-        "commands-core" "commands-core2"
-        "commands-edit" "commands-edit2"
-        "commands-file" "commands-file2"
-        "commands-search" "commands-search2"
-        "commands-sexp" "commands-sexp2"
-        "commands-shell" "commands-shell2"
-        "commands-vcs" "commands-vcs2"
-        "commands-ide" "commands-ide2"
-        "commands-lsp"
-        "commands-modes" "commands-modes2"
-        "commands-parity" "commands-parity2"
-        "commands-parity3" "commands-parity3b"
-        "commands-parity4" "commands-parity5"
-        "commands-config" "commands-config2"
-        "commands-aliases" "commands-aliases2"
-        "commands"
-        ;; Qt app
-        "app" "main")))))
+(let ((boot-so-files (existing-so-files (unique-strings (wpo-missing-so-files)))))
+  (unless (null? boot-so-files)
+    (printf "  Boot file includes ~a WPO-missing libraries:~n" (length boot-so-files))
+    (for-each (lambda (path) (printf "    ~a~n" path)) boot-so-files))
+  (apply make-boot-file "jemacs-qt.boot" '("scheme" "petite") boot-so-files))
 
 ;; --- Step 4: Generate C headers with embedded data ---
 (printf "[4/7] Embedding boot files + program as C headers...~n")
@@ -436,7 +298,8 @@
          (include-dir chez-dir)
          ;; Generate the C file by scanning ALL FFI source files:
          ;;   chez-qt/ffi.ss, chez-pcre2/ffi.ss — specific files
-         ;;   jsh-dir/, jerboa-dir/, lib/jerboa-emacs/ — recursive (catches all transitive deps)
+         ;;   jsh-dir/, jerboa-dir/, chez-ssl-dir/src, lib/jerboa-emacs/ — recursive
+         ;;   (catches all transitive deps)
          ;; Strip Scheme line comments (;; ...) before matching to avoid placeholder strings
          ;; like "c_name", "c_func", "c_function_name" that appear in macro doc comments.
          ;; Two patterns extracted:
@@ -444,19 +307,20 @@
          ;;   define-foreign name "c-name"  — jsh macro (C name is the second string)
          (gen-cmd
            (format
-             "{ { cat ~a ~a; find ~a ~a/jerboa ~a/std/os ~a/std/net ~a/std/crypto ~a/std/security ~a/chez-scintilla lib/jerboa-emacs lib/jerboa vendor -name '*.sls' -o -name '*.ss' | xargs cat 2>/dev/null; } | \
+             "{ { cat ~a ~a; find ~a ~a/jerboa ~a/std/os ~a/std/net ~a/std/crypto ~a/std/security ~a/chez-scintilla ~a/src lib/jerboa-emacs lib/jerboa -name '*.sls' -o -name '*.ss' | xargs cat 2>/dev/null; } | \
 sed 's/;;.*//' | grep -oE '(foreign-procedure|foreign-entry\\?) \"[^\"]*\"' | sed 's/.* \"//;s/\"//'; \
 { cat ~a ~a; } | sed 's/;;.*//' | grep -o 'define-optional-ffi [^ ]* \"[^\"]*\"' | sed 's/.*define-optional-ffi [^ ]* \"//;s/\"//'; \
 find ~a -name '*.sls' -o -name '*.ss' | \
   xargs cat 2>/dev/null | tr '\\n' ' ' | \
   grep -oE 'define-foreign [^ ]+ +\"[^\"]+\"' | \
   sed 's/.*define-foreign [^ ]* *\"//;s/\".*//'; } | \
-sort -u | grep -v '^$' | grep -v '^_NSGetExecutablePath$' | grep -v '^io_uring_' | \
+sort -u | grep -v '^$' | grep -E '^[A-Za-z_][A-Za-z0-9_]*$' | grep -v '^_NSGetExecutablePath$' | grep -v '^io_uring_' | \
 grep -v '^jerboa_' | grep -v '^SSL_' | grep -v '^TLS_' | grep -v '^EVP_' | \
 grep -v '^CRYPTO_' | grep -v '^PKCS5_' | grep -v '^RAND_' | \
 grep -v '^QRcode_' | grep -v '^embed_encrypt$' | grep -v '^embed_random_bytes$' | \
 grep -v '^kqueue$' | grep -v '^kevent$' | grep -v '^sandbox_' | \
-grep -v '^__error$' > /tmp/ffi_syms.txt && \
+grep -v '^__error$' | grep -v '^__errno$' | grep -v '^cap_' | \
+grep -v '^host_statistics' | grep -v '^mach_' | grep -v '^sysctlbyname$' > /tmp/ffi_syms.txt && \
 awk '\
 BEGIN{ print \"/* Auto-generated — do not edit */\"; \
        print \"#include \\\"scheme.h\\\"\"; print \"\"; } \
@@ -469,7 +333,7 @@ echo \"}\" >> qt_static_symbols.c && \
 rm /tmp/ffi_syms.txt && \
 echo OK"
              ffi-path pcre2-ffi-path
-             jsh-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir sci-dir
+             jsh-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir jerboa-dir sci-dir chez-ssl-dir
              ffi-path pcre2-ffi-path
              jsh-dir))
          (result (shell-output gen-cmd "")))
@@ -511,7 +375,7 @@ echo OK"
       (exit 1))))
 
 ;; jsh coreutils stubs (jsh_* Rust uutils symbols — stubs for static binary)
-;; The Rust libjsh_coreutils.a is not in the Docker image; these stubs allow linking.
+;; The Rust libjsh_coreutils.a is not in the deps image; these stubs allow linking.
 ;; At runtime, in-process coreutils commands return an error; vterm PTY is unaffected.
 (when jemacs-static?
   (let* ((cmd "gcc -c -O2 -o jemacs-qt-jsh-coreutils-stubs.o support/jsh_coreutils_stubs.c -Wall 2>&1"))
@@ -519,11 +383,16 @@ echo OK"
       (display "Error: jsh_coreutils_stubs.c compilation failed\n")
       (exit 1))))
 
-;; jsh embed-crypto (pure C crypto for embed encryption — no external deps)
+;; jsh embed-crypto. Older jsh trees had embed-crypto.c; newer ones use
+;; libjerboa_native. If neither is available, compile explicit failing stubs
+;; so non-embed editor features still link and encrypted embed calls fail.
 (when (or jemacs-static? macos-build?)
   (let* ((jsh-root (path-parent jsh-dir))
-         (cmd (format "gcc -c -O2 -o jemacs-qt-embed-crypto.o ~a/embed-crypto.c -I~a -Wall 2>&1"
-                      jsh-root jsh-root)))
+         (embed-src (format "~a/embed-crypto.c" jsh-root))
+         (fallback-src "support/jsh_embed_crypto_stubs.c")
+         (src (if (file-exists? embed-src) embed-src fallback-src))
+         (cmd (format "gcc -c -O2 -o jemacs-qt-embed-crypto.o ~a -I~a -Wall 2>&1"
+                      src jsh-root)))
     (unless (= 0 (system cmd))
       (display "Error: embed-crypto.c compilation failed\n")
       (exit 1))))
@@ -681,7 +550,7 @@ grep -v '^$' | grep -v '^register_static_foreign_symbols$'")
 ;; --- Step 6: Link native binary ---
 (printf "[6/7] Linking native binary...~n")
 (if jemacs-static?
-  ;; ─── Static link (Docker musl build) ───────────────────────────────────
+  ;; ─── Static link (Podman musl build) ───────────────────────────────────
   ;; -static: fully static binary (musl embeds dynamic linker, dlopen works)
   ;; -Wl,--export-dynamic: export main binary symbols so the embedded .so
   ;;   (loaded via Sscheme_script/dlopen from memfd) can find Chez kernel symbols
diff --git a/build-binary.ss b/build-binary.ss
index ecf22ca..bd5651d 100644
--- a/build-binary.ss
+++ b/build-binary.ss
@@ -148,191 +148,76 @@
 
 ;; --- Step 2: Whole-program optimization ---
 (printf "[2/6] Running whole-program optimization...~n")
+(define wpo-missing-libraries '())
 (let ((missing (compile-whole-program "main.wpo" "jemacs-all.so")))
+  (set! wpo-missing-libraries missing)
   (unless (null? missing)
     (printf "  WPO: ~a libraries not incorporated (missing .wpo):~n" (length missing))
     (for-each (lambda (lib) (printf "    ~a~n" lib)) missing)))
 
 ;; --- Step 3: Make libs-only boot file ---
 (printf "[3/6] Creating libs-only boot file...~n")
+(define (symbol-path parts)
+  (let loop ((rest parts) (acc ""))
+    (cond
+      ((null? rest) acc)
+      ((string=? acc "")
+       (loop (cdr rest) (symbol->string (car rest))))
+      (else
+       (loop (cdr rest) (string-append acc "/" (symbol->string (car rest))))))))
+
+(define (library-ref->so-path lib)
+  (and (pair? lib)
+       (let ((head (car lib))
+             (tail (cdr lib)))
+         (case head
+           ((std)
+            (format "~a/std/~a.so" jerboa-dir (symbol-path tail)))
+           ((jerboa)
+            (if (and (pair? tail) (eq? (car tail) 'repl-socket))
+                "lib/jerboa/repl-socket.so"
+                (format "~a/jerboa/~a.so" jerboa-dir (symbol-path tail))))
+           ((jsh)
+            (format "~a/jsh/~a.so" jsh-dir (symbol-path tail)))
+           ((compat)
+            (if (and (pair? tail) (eq? (car tail) 'gambit))
+                (format "~a/compat/gambit.so" jsh-dir)
+                (format "~a/compat/~a.so" gherkin-dir (symbol-path tail))))
+           ((runtime)
+            (format "~a/runtime/~a.so" gherkin-dir (symbol-path tail)))
+           ((chez-pcre2)
+            (format "~a/chez-pcre2/~a.so" pcre2-dir (symbol-path tail)))
+           ((chez-scintilla)
+            (format "~a/chez-scintilla/~a.so" sci-dir (symbol-path tail)))
+           ((chez-qt)
+            (format "~a/chez-qt/~a.so" qt-dir (symbol-path tail)))
+           ((chez-ssl)
+            (format "~a/src/chez-ssl.so" chez-ssl-dir))
+           ((chez-https)
+            (format "~a/chez-https.so" chez-https-dir))
+           ((jerboa-aws)
+            (format "~a/jerboa-aws/~a.so" jaws-dir (symbol-path tail)))
+           ((jerboa-emacs)
+            (format "lib/jerboa-emacs/~a.so" (symbol-path tail)))
+           (else #f)))))
+
+(define (wpo-missing-so-files)
+  (filter values (map library-ref->so-path wpo-missing-libraries)))
+
+(define (unique-strings strings)
+  (let loop ((rest strings) (seen '()) (acc '()))
+    (cond
+      ((null? rest) (reverse acc))
+      ((member (car rest) seen) (loop (cdr rest) seen acc))
+      (else (loop (cdr rest) (cons (car rest) seen) (cons (car rest) acc))))))
+
 (define (existing-so-files paths)
   (filter file-exists? paths))
-(apply make-boot-file "jemacs.boot" '("scheme" "petite")
-  (existing-so-files
-  (append
-    ;; Jerboa runtime (no deps on other jerboa libs)
-    (map (lambda (m) (format "~a/~a.so" jerboa-dir m))
-      '("jerboa/runtime"))
-    ;; Jerboa stdlib — include all available .so modules (existing-so-files filters missing ones)
-    (map (lambda (m) (format "~a/~a.so" jerboa-dir m))
-      '("std/error"
-        "std/format"
-        "std/sort"
-        "std/pregexp"
-        "std/foreign"
-        "std/iter"
-        "std/log"