Implement Qt robustness and AWS feature flags

ober

cb0644d7a4fad04264c8db1f55aa45f634d54a4f

diff --git a/Dockerfile.qt b/Dockerfile.qt
index f3173fd..cfd99e5 100644
--- a/Dockerfile.qt
+++ b/Dockerfile.qt
@@ -278,6 +278,8 @@ RUN ln -s /build/chez-musl /opt/chez
 COPY . /src
 WORKDIR /src
 
+ARG JEMACS_FEATURES=""
+ENV JEMACS_FEATURES=${JEMACS_FEATURES}
 RUN make linux-qt-local
 
 # Verify
diff --git a/Makefile b/Makefile
index 1008228..8f6a0b3 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,27 @@ CHEZ_SSL_REPO      ?= https://git.sr.ht/~lisp/chez-ssl
 CHEZ_HTTPS_REPO    ?= https://git.sr.ht/~lisp/chez-https
 JERBOA_AWS_REPO    ?= https://git.sr.ht/~lisp/jerboa-aws
 
-VENDOR_REPOS := jerboa jerboa-shell chez-pcre2 chez-scintilla chez-qt chez-ssl chez-https jerboa-aws
+JEMACS_FEATURES ?=
+export JEMACS_FEATURES
+
+empty :=
+space := $(empty) $(empty)
+comma := ,
+JEMACS_ALL_FEATURES := aws
+JEMACS_FEATURE_LIST := $(strip $(subst $(comma),$(space),$(JEMACS_FEATURES)))
+ifneq ($(filter all,$(JEMACS_FEATURE_LIST)),)
+  JEMACS_ENABLED_FEATURES := $(JEMACS_ALL_FEATURES)
+else ifneq ($(filter none,$(JEMACS_FEATURE_LIST)),)
+  JEMACS_ENABLED_FEATURES :=
+else
+  JEMACS_ENABLED_FEATURES := $(filter $(JEMACS_ALL_FEATURES),$(JEMACS_FEATURE_LIST))
+endif
+JEMACS_ENABLE_AWS := $(if $(filter aws,$(JEMACS_ENABLED_FEATURES)),1,0)
+
+VENDOR_REPOS := jerboa jerboa-shell chez-pcre2 chez-scintilla chez-qt chez-ssl chez-https
+ifeq ($(JEMACS_ENABLE_AWS),1)
+  VENDOR_REPOS += jerboa-aws
+endif
 
 JERBOA    ?= $(VENDOR)/jerboa
 SCHEME    ?= $(JERBOA)/.chez/bin/scheme
@@ -33,7 +53,11 @@ CHTTPS    ?= $(CHEZ_HTTPS_ROOT)/src
 CQT       ?= $(VENDOR)/chez-qt
 CHEZ_PCRE2_ROOT ?= $(VENDOR)/chez-pcre2
 CHEZ_SCINTILLA_ROOT ?= $(VENDOR)/chez-scintilla
-LIBDIRS   = --libdirs lib:$(JERBOA)/lib:$(JSH):$(COREUTILS):$(JSH_AWK):$(JSH_SED):$(CHEZ_SSH):$(CHEZ_SQLITE):$(CHEZ_CRYPTO):$(CHEZ_FUSE):$(GHERKIN):$(CHEZ_PCRE2_ROOT):$(CHEZ_SCINTILLA_ROOT)/src:$(CQT):$(JAWS):$(CSSL):$(CHTTPS)
+AWS_LIBDIRS :=
+ifeq ($(JEMACS_ENABLE_AWS),1)
+  AWS_LIBDIRS := :$(JAWS):$(CSSL):$(CHTTPS)
+endif
+LIBDIRS   = --libdirs lib:$(JERBOA)/lib:$(JSH):$(COREUTILS):$(JSH_AWK):$(JSH_SED):$(CHEZ_SSH):$(CHEZ_SQLITE):$(CHEZ_CRYPTO):$(CHEZ_FUSE):$(GHERKIN):$(CHEZ_PCRE2_ROOT):$(CHEZ_SCINTILLA_ROOT)/src:$(CQT)$(AWS_LIBDIRS)
 JERBUILD  = $(SCHEME) --libdirs $(JERBOA)/lib --script $(JERBOA)/jerbuild.ss
 
 # --- Platform detection -------------------------------------------------------
@@ -63,17 +87,25 @@ else
   TS_INC      := /opt/tree-sitter-include
   TS_LIB_DIR  := /opt/tree-sitter-lib
 endif
-PRELOAD_ENV := $(PRELOAD_VAR)=./qt_chez_shim.$(SHLIB_EXT):./libjerboa_native.$(SHLIB_EXT):./libjsh-ffi.$(SHLIB_EXT)
+NATIVE_LIB := $(JERBOA)/lib/libjerboa_native.$(SHLIB_EXT)
+SSL_SHIM := $(CHEZ_SSL_ROOT)/chez_ssl_shim.$(SHLIB_EXT)
+PRELOAD_ENV := $(PRELOAD_VAR)=./libqt_shim.$(SHLIB_EXT):./qt_chez_shim.$(SHLIB_EXT):$(NATIVE_LIB):./libjsh-ffi.$(SHLIB_EXT):./libjsh_coreutils_stub.$(SHLIB_EXT):$(SSL_SHIM)
 # -----------------------------------------------------------------------------
 
 export CHEZ_SCINTILLA_LIB := $(CHEZ_SCINTILLA_ROOT)
 export CHEZ_PCRE2_LIB := $(CHEZ_PCRE2_ROOT)
 export JSH_FFI_LIB := $(JSH_ROOT)
+export CHEZ_SSL_DIR := $(CHEZ_SSL_ROOT)
 export CHEZ_QT_LIB := .
 export CHEZ_QT_SHIM_DIR := .
 ifeq ($(UNAME_S),Darwin)
   export CHEZ_DIR := $(shell ls -d /opt/homebrew/lib/csv*/tarm64osx 2>/dev/null | head -1)
 endif
+SCHEME_PREFIX = $(abspath $(dir $(SCHEME))/..)
+SCHEME_MT = $(shell if [ -x "$(SCHEME)" ]; then printf '(display (machine-type))\n' | "$(SCHEME)" -q 2>/dev/null; fi)
+SCHEME_CHEZ_DIR = $(shell if [ -n "$(SCHEME_MT)" ]; then ls -d "$(SCHEME_PREFIX)"/lib/csv*/"$(SCHEME_MT)" 2>/dev/null | head -1; fi)
+CHEZ_DIR ?= $(SCHEME_CHEZ_DIR)
+export CHEZ_DIR
 
 .PHONY: all vendor-deps deps build rebuild run test-tier0 test-tier2 test-tier3 test-tier4 test-tier5 test-org test-extra test clean clean-generated \
         test-org-duration test-org-element test-org-fold test-org-footnote \
@@ -86,6 +118,9 @@ endif
         linux-tui linux-tui-local \
         linux-qt linux-qt-local \
         stress-run stress-run-static stress-test stress-burn stress-burn-static \
+        stress-window stress-window-static stress-buffer stress-buffer-static \
+        stress-edit stress-edit-static stress-file stress-file-static \
+        stress-chaos stress-chaos-static check-generated test-command-registry \
         scenario-test scenario-burn scenario-burn-static \
         test-behavioral
 
@@ -108,7 +143,10 @@ all:
 	@echo "  test-tier3     Editor core"
 	@echo "  test-tier4     Shell integration"
 	@echo "  test-tier5     Full editor commands"
+	@echo "  check-generated  Verify generated lib/*.sls is in sync with src/*.ss"
+	@echo "  stress-window  Focused Qt window stress profile"
 	@echo "  clean          Remove build artifacts"
+	@echo "  JEMACS_FEATURES=aws make <target>  Enable optional AWS EC2 SSH support"
 
 vendor-deps:
 	@echo "=== Vendoring chez-* and jerboa-* dependencies into $(VENDOR) ==="
@@ -139,6 +177,7 @@ vendor-deps:
 	    git clone --depth 1 "$$url" "$$dest"; \
 	  fi; \
 	done
+	@scripts/patch-jerboa-aws-compat.sh "$(CURDIR)"
 	@echo "=== Vendor complete ==="
 
 deps: vendor-deps
@@ -154,6 +193,10 @@ build: deps
 rebuild: deps
 	$(JERBUILD) src/ lib/ --force
 
+check-generated:
+	$(MAKE) build
+	git diff --exit-code -- lib
+
 run: build vterm_shim.$(SHLIB_EXT)
 	$(SCHEME) $(LIBDIRS) --script main.ss
 
@@ -247,6 +290,18 @@ libqt_shim.$(SHLIB_EXT): vendor/qt_shim.cpp
 qt_chez_shim.$(SHLIB_EXT): vendor/qt_chez_shim.c vendor/qt_shim.h
 	gcc $(SHLIB_FLAGS) -O2 -o qt_chez_shim.$(SHLIB_EXT) vendor/qt_chez_shim.c -Ivendor -DQT_SCINTILLA_AVAILABLE -Wall
 
+libjsh-ffi.$(SHLIB_EXT): $(JSH_ROOT)/ffi-shim.c
+	gcc $(SHLIB_FLAGS) -O2 -o libjsh-ffi.$(SHLIB_EXT) $(JSH_ROOT)/ffi-shim.c -Wall
+
+libjsh_coreutils_stub.$(SHLIB_EXT): vendor/libjsh_coreutils_stub.a
+	gcc $(SHLIB_FLAGS) -o libjsh_coreutils_stub.$(SHLIB_EXT) -Wl,--whole-archive vendor/libjsh_coreutils_stub.a -Wl,--no-whole-archive
+
+$(NATIVE_LIB):
+	$(MAKE) -C $(JERBOA) native
+
+$(SSL_SHIM): $(CHEZ_SSL_ROOT)/chez_ssl_shim.c
+	$(MAKE) -C $(CHEZ_SSL_ROOT)
+
 # macOS native binary — compile all modules + link jemacs-qt binary
 macos: build libqt_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) repl_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT)
 	$(MAKE) -C $(CHEZ_PCRE2_ROOT) SCHEME=$(SCHEME)
@@ -328,7 +383,7 @@ build-qt: build
 	@echo "🎉 PLAN.MD COMPLETE - READY FOR Qt EXECUTABLE BUILD"
 	@echo "════════════════════════════════════════════════════════════════"
 
-test: build test-tier0 test-tier2 test-tier3 test-tier4 test-tier5 test-org test-extra
+test: build test-tier0 test-tier2 test-tier3 test-tier4 test-tier5 test-org test-extra test-command-registry
 
 test-tier0: vterm_shim.$(SHLIB_EXT) repl_shim.$(SHLIB_EXT)
 	$(SCHEME) $(LIBDIRS) --script tests/test-tier0.ss
@@ -336,6 +391,9 @@ test-tier0: vterm_shim.$(SHLIB_EXT) repl_shim.$(SHLIB_EXT)
 test-tier2:
 	$(SCHEME) $(LIBDIRS) --script tests/test-tier2.ss
 
+test-command-registry:
+	scripts/audit-command-registry.sh
+
 test-tier3:
 	$(SCHEME) $(LIBDIRS) --script tests/test-tier3.ss
 
@@ -413,9 +471,13 @@ test-vtscreen:
 test-debug-repl:
 	$(SCHEME) $(LIBDIRS) --program tests/test-debug-repl.ss
 
-test-qt: build
+test-qt: build repl_shim.$(SHLIB_EXT) libqt_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
 	QT_QPA_PLATFORM=offscreen $(PRELOAD_ENV) $(SCHEME) $(LIBDIRS) --script tests/test-qt.ss
-	QT_QPA_PLATFORM=offscreen $(PRELOAD_ENV) $(SCHEME) $(LIBDIRS) --script tests/test-qt-part2.ss
+	@if [ -f tests/test-qt-part2.ss ]; then \
+	  QT_QPA_PLATFORM=offscreen $(PRELOAD_ENV) $(SCHEME) $(LIBDIRS) --script tests/test-qt-part2.ss; \
+	else \
+	  echo "SKIP: tests/test-qt-part2.ss not present"; \
+	fi
 
 # End-to-end Qt tests: Xvfb + xdotool + IPC REPL (requires xvfb, xdotool, nc)
 test-qt-e2e:
@@ -424,8 +486,8 @@ test-qt-e2e:
 test-emacs:
 	$(SCHEME) $(LIBDIRS) --program tests/test-emacs.ss
 
-test-functional:
-	$(SCHEME) $(LIBDIRS) --program tests/test-functional.ss
+test-functional: build libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
+	$(PRELOAD_ENV) $(SCHEME) $(LIBDIRS) --program tests/test-functional.ss
 
 test-pty:
 	$(SCHEME) $(LIBDIRS) --script tests/test-pty.ss
@@ -495,6 +557,26 @@ QT_SRC       ?= $(CQT)
 JAWS_SRC     ?= $(JAWS)
 CSSL_SRC     ?= $(CHEZ_SSL_ROOT)
 CHTTPS_SRC   ?= $(CHEZ_HTTPS_ROOT)
+AWS_PODMAN_BUILD_CONTEXTS :=
+AWS_PODMAN_RUN_MOUNTS :=
+AWS_STATIC_LIBDIRS :=
+AWS_STATIC_ENV := JEMACS_AWS_DISABLED=1
+AWS_LOCAL_STATIC_LIBDIRS :=
+AWS_LOCAL_STATIC_ENV := JEMACS_AWS_DISABLED=1
+ifeq ($(JEMACS_ENABLE_AWS),1)
+  AWS_PODMAN_BUILD_CONTEXTS := \
+	  --build-context jaws-src=$(JAWS_SRC) \
+	  --build-context chez-ssl-src=$(CSSL_SRC) \
+	  --build-context chez-https-src=$(CHTTPS_SRC)
+  AWS_PODMAN_RUN_MOUNTS := \
+	  -v $(JAWS_SRC):/host-jaws:ro \
+	  -v $(CSSL_SRC):/host-chez-ssl:ro \
+	  -v $(CHTTPS_SRC):/host-chez-https:ro
+  AWS_STATIC_LIBDIRS := :/deps/jerboa-aws:/deps/chez-ssl/src:/deps/chez-https/src
+  AWS_STATIC_ENV := JAWS_DIR=/deps/jerboa-aws CHEZ_SSL_DIR=/deps/chez-ssl CHEZ_HTTPS_DIR=/deps/chez-https/src
+  AWS_LOCAL_STATIC_LIBDIRS := :$(JAWS):$(CSSL):$(CHTTPS)
+  AWS_LOCAL_STATIC_ENV := JAWS_DIR=$(JAWS) CHEZ_SSL_DIR=$(CHEZ_SSL_ROOT) CHEZ_HTTPS_DIR=$(CHTTPS)
+endif
 # Use stub if the Rust musl build hasn't been compiled yet (regular file check)
 _RUST_COREUTILS := $(JSH_SRC)/rust-coreutils/target/x86_64-unknown-linux-musl/release/libjsh_coreutils.a
 JSH_COREUTILS_LIB ?= $(shell test -f $(_RUST_COREUTILS) && echo $(_RUST_COREUTILS) || echo $(CURDIR)/vendor/libjsh_coreutils_stub.a)
@@ -519,9 +601,7 @@ podman-deps: check-podman
 	  --build-context pcre2-src=$(PCRE2_SRC) \
 	  --build-context sci-src=$(SCI_SRC) \
 	  --build-context qt-src=$(QT_SRC) \
-	  --build-context jaws-src=$(JAWS_SRC) \
-	  --build-context chez-ssl-src=$(CSSL_SRC) \
-	  --build-context chez-https-src=$(CHTTPS_SRC) \
+	  $(AWS_PODMAN_BUILD_CONTEXTS) \
 	  -t $(DEPS_IMAGE) \
 	  $(CURDIR)
 
@@ -618,21 +698,26 @@ build-jemacs-qt-static: check-root
 	    /src/support/treesitter_shim.c -Wall && \
 	gcc -c -O2 -o /tmp/jemacs-build/treesitter_queries.o \
 	    /src/support/treesitter_queries.c -Wall && \
-	cp /src/vendor/chez-ssl-static.sls /deps/chez-ssl/src/chez-ssl.sls && \
-	cp /src/vendor/jerboa-aws-crypto-native.sls /deps/jerboa-aws/jerboa-aws/crypto.sls && \
-	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 && \
-		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 && \
+	if [ "$(JEMACS_ENABLE_AWS)" = "1" ]; then \
+	  cp /src/vendor/chez-ssl-static.sls /deps/chez-ssl/src/chez-ssl.sls && \
+	  cp /src/vendor/jerboa-aws-crypto-native.sls /deps/jerboa-aws/jerboa-aws/crypto.sls && \
+	  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 && \
+	  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; \
+	else \
+	  echo "Skipping AWS static feature modules"; \
+	fi && \
 		JEMACS_STATIC=1 \
+	JEMACS_FEATURES="$(JEMACS_FEATURES)" \
 	CHEZ_DIR=$(CHEZ_MUSL_DIR) \
 	JERBOA_DIR=/deps/jerboa/lib \
 	JSH_DIR=/deps/jsh/src \
@@ -642,9 +727,7 @@ build-jemacs-qt-static: check-root
 	CHEZ_QT_DIR=/deps/chez-qt \
 	CHEZ_QT_SHIM_DIR=/deps/qt-shim \
 	JSH_COREUTILS_LIB=/deps/jsh/libjsh_coreutils.a \
-	JAWS_DIR=/deps/jerboa-aws \
-	CHEZ_SSL_DIR=/deps/chez-ssl \
-	CHEZ_HTTPS_DIR=/deps/chez-https/src \
+	$(AWS_STATIC_ENV) \
 	TREE_SITTER_INCLUDE=/opt/tree-sitter-include \
 	TREE_SITTER_LIB=/opt/tree-sitter-lib \
 	TREE_SITTER_GRAMMARS=/opt/tree-sitter-grammars \
@@ -652,7 +735,7 @@ build-jemacs-qt-static: check-root
 	TREE_SITTER_QUERIES_OBJ=/tmp/jemacs-build/treesitter_queries.o \
 	PKG_CONFIG_PATH=/opt/qt6-static/lib/pkgconfig \
 	/opt/chez/bin/scheme \
-	  --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 \
+	  --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$(AWS_STATIC_LIBDIRS) \
 	  --script build-binary-qt.ss
 
 linux-static-qt-podman: ensure-podman-deps
@@ -664,9 +747,7 @@ linux-static-qt-podman: ensure-podman-deps
 	  -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 \
-	  -v $(CHTTPS_SRC):/host-chez-https:ro \
+	  $(AWS_PODMAN_RUN_MOUNTS) \
 	  $(DEPS_IMAGE) \
 	  sh -c "apk add --no-cache libvterm-dev libvterm-static openssl-dev; \
 	         if [ ! -f /usr/lib/libssl.a ]; then \
@@ -690,14 +771,18 @@ linux-static-qt-podman: ensure-podman-deps
 	         cd /deps/jerboa/lib && /opt/chez/bin/scheme --libdirs /deps/jerboa/lib \
 	           -q --script /tmp/compile-jerboa-core.ss && \
 	         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'; \
+	         if [ '$(JEMACS_ENABLE_AWS)' = '1' ]; then \
+	           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'; \
+	         else \
+	           echo 'SYNC: AWS feature disabled'; \
+	         fi; \
 	         mkdir -p /tmp/jemacs-build && \
-	         exec env HOME=/tmp/jemacs-build sh -c '\
-	           cd /src && make build-jemacs-qt-static'"
+	         exec env HOME=/tmp/jemacs-build JEMACS_FEATURES='$(JEMACS_FEATURES)' \
+	           make -C /src build-jemacs-qt-static"
 
 # =============================================================================
 # Static TUI binary (Podman-based, Alpine musl)
@@ -913,7 +998,9 @@ linux-tui-local: vendor-deps
 # 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 .
+	$(PODMAN) build $(PODMAN_BUILD_FLAGS) --platform $(PODMAN_PLATFORM) \
+	  --build-arg JEMACS_FEATURES="$(JEMACS_FEATURES)" \
+	  -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
@@ -996,24 +1083,28 @@ linux-qt-local: vendor-deps
 	JEMACS_STATIC=1 $(MUSL_SCHEME) --libdirs lib \
 	  --compile-imported-libraries --script vendor/jerboa-compile-repl-socket.ss
 	rm -f lib/jerboa/*.wpo
-	# Compile SSL/HTTPS/AWS
-	cp vendor/chez-ssl-static.sls vendor/chez-ssl/src/chez-ssl.sls
-	cp vendor/jerboa-aws-crypto-native.sls $(JAWS)/jerboa-aws/crypto.sls
-	find vendor/chez-ssl -name '*.so' -delete; find vendor/chez-ssl -name '*.wpo' -delete
-	find vendor/chez-https -name '*.so' -delete; find vendor/chez-https -name '*.wpo' -delete
-	find vendor/jerboa-aws -name '*.so' -delete; find vendor/jerboa-aws -name '*.wpo' -delete
-	JEMACS_STATIC=1 $(MUSL_SCHEME) \
-	  --libdirs vendor/chez-ssl/src:$(MUSL_JERBOA)/lib \
-	  --compile-imported-libraries -q --script vendor/chez-ssl-compile-libs.ss
-	find vendor/chez-ssl -name '*.wpo' -delete
-	JEMACS_STATIC=1 $(MUSL_SCHEME) \
-	  --libdirs vendor/chez-https/src:vendor/chez-ssl/src \
-	  --compile-imported-libraries -q --script vendor/chez-https-compile-libs.ss
-	find vendor/chez-https -name '*.wpo' -delete
-	JEMACS_STATIC=1 $(MUSL_SCHEME) \
-	  --libdirs $(JAWS):$(CHTTPS):$(CSSL):$(MUSL_JERBOA)/lib \
-	  --compile-imported-libraries -q --script vendor/jerboa-aws-compile-libs.ss
-	find vendor/jerboa-aws -name '*.wpo' -delete
+	# Compile optional SSL/HTTPS/AWS feature modules
+	@if [ "$(JEMACS_ENABLE_AWS)" = "1" ]; then \
+	  cp vendor/chez-ssl-static.sls vendor/chez-ssl/src/chez-ssl.sls && \
+	  cp vendor/jerboa-aws-crypto-native.sls $(JAWS)/jerboa-aws/crypto.sls && \
+	  find vendor/chez-ssl -name '*.so' -delete; find vendor/chez-ssl -name '*.wpo' -delete; \
+	  find vendor/chez-https -name '*.so' -delete; find vendor/chez-https -name '*.wpo' -delete; \
+	  find vendor/jerboa-aws -name '*.so' -delete; find vendor/jerboa-aws -name '*.wpo' -delete; \
+	  JEMACS_STATIC=1 $(MUSL_SCHEME) \
+	    --libdirs vendor/chez-ssl/src:$(MUSL_JERBOA)/lib \
+	    --compile-imported-libraries -q --script vendor/chez-ssl-compile-libs.ss && \
+	  find vendor/chez-ssl -name '*.wpo' -delete && \
+	  JEMACS_STATIC=1 $(MUSL_SCHEME) \
+	    --libdirs vendor/chez-https/src:vendor/chez-ssl/src \
+	    --compile-imported-libraries -q --script vendor/chez-https-compile-libs.ss && \
+	  find vendor/chez-https -name '*.wpo' -delete && \
+	  JEMACS_STATIC=1 $(MUSL_SCHEME) \
+	    --libdirs $(JAWS):$(CHTTPS):$(CSSL):$(MUSL_JERBOA)/lib \
+	    --compile-imported-libraries -q --script vendor/jerboa-aws-compile-libs.ss && \
+	  find vendor/jerboa-aws -name '*.wpo' -delete; \
+	else \
+	  echo "Skipping AWS static feature modules"; \
+	fi
 	# Build tree-sitter C shim objects
 	mkdir -p /tmp/jemacs-build
 	gcc -c -O2 -I/opt/tree-sitter-include -o /tmp/jemacs-build/treesitter_shim.o \
@@ -1022,6 +1113,7 @@ linux-qt-local: vendor-deps
 	    support/treesitter_queries.c -Wall
 	# Run the main Qt build script
 	JEMACS_STATIC=1 \
+	JEMACS_FEATURES="$(JEMACS_FEATURES)" \
 	CHEZ_DIR=$(MUSL_CHEZ_DIR) \
 	JERBOA_DIR=$(MUSL_JERBOA)/lib \
 	JSH_DIR=$(MUSL_JSH) \
@@ -1031,9 +1123,7 @@ linux-qt-local: vendor-deps
 	CHEZ_QT_DIR=/tmp/jemacs-build/chez-qt \
 	CHEZ_QT_SHIM_DIR=/opt/qt-shim \
 	JSH_COREUTILS_LIB=vendor/libjsh_coreutils_stub.a \
-	JAWS_DIR=$(JAWS) \
-	CHEZ_SSL_DIR=$(CHEZ_SSL_ROOT) \
-	CHEZ_HTTPS_DIR=$(CHTTPS) \
+	$(AWS_LOCAL_STATIC_ENV) \
 	TREE_SITTER_INCLUDE=/opt/tree-sitter-include \
 	TREE_SITTER_LIB=/opt/tree-sitter-lib \
 	TREE_SITTER_GRAMMARS=/opt/tree-sitter-grammars \
@@ -1041,7 +1131,7 @@ linux-qt-local: vendor-deps
 	TREE_SITTER_QUERIES_OBJ=/tmp/jemacs-build/treesitter_queries.o \
 	PKG_CONFIG_PATH=/opt/qt6-static/lib/pkgconfig \
 	$(MUSL_SCHEME) \
-	  --libdirs lib:$(MUSL_JERBOA)/lib:$(MUSL_JSH):$(COREUTILS):$(JSH_AWK):$(JSH_SED):$(CHEZ_SSH):$(CHEZ_SQLITE):$(CHEZ_CRYPTO):$(CHEZ_FUSE):$(GHERKIN):$(MUSL_PCRE2):$(MUSL_SCINTILLA)/src:/tmp/jemacs-build/chez-qt:$(JAWS):$(CSSL):$(CHTTPS) \
+	  --libdirs lib:$(MUSL_JERBOA)/lib:$(MUSL_JSH):$(COREUTILS):$(JSH_AWK):$(JSH_SED):$(CHEZ_SSH):$(CHEZ_SQLITE):$(CHEZ_CRYPTO):$(CHEZ_FUSE):$(GHERKIN):$(MUSL_PCRE2):$(MUSL_SCINTILLA)/src:/tmp/jemacs-build/chez-qt$(AWS_LOCAL_STATIC_LIBDIRS) \
 	  --script build-binary-qt.ss
 	@echo ""
 	@echo "=== jemacs-qt static binary built ==="
@@ -1053,6 +1143,9 @@ linux-qt-local: vendor-deps
 # =============================================================================
 
 STRESS_PORT ?= 9999
+STRESS_PROFILE ?= chaos
+STRESS_CYCLES ?=
+STRESS_ENV = SCHEME="$(SCHEME)" LIBDIRS="$(LIBDIRS)" XVFB_RUN="$(XVFB_RUN)" QT_MAIN="$(CURDIR)/qt-main.ss" JEMACS_QT="$(CURDIR)/jemacs-qt" STRESS_CYCLES="$(STRESS_CYCLES)"
 
 # Launch jemacs-qt (interpreted) headless with REPL for manual stress testing
 stress-run: build repl_shim.so libqt_shim.so vterm_shim.so qt_chez_shim.so
@@ -1072,67 +1165,46 @@ stress-run-static:
 
 # Run the stress test driver against an already-running jemacs-qt REPL
 stress-test:
-	$(SCHEME) $(LIBDIRS) --script tests/stress-test.ss --port $(STRESS_PORT)
+	$(SCHEME) $(LIBDIRS) --script tests/stress-test.ss --port $(STRESS_PORT) --profile $(STRESS_PROFILE)
 
-# All-in-one: launch interpreted jemacs-qt + run stress test driver
-stress-burn: build repl_shim.so libqt_shim.so vterm_shim.so qt_chez_shim.so
-	@echo "=== Starting jemacs-qt stress burn-in ==="
-	@rm -f $(HOME)/.jerboa-repl-port stress-test.log
-	@xvfb-run -a env CHEZ_QT_SHIM_DIR=$(CURDIR) \
-	  $(SCHEME) $(LIBDIRS) --script $(CURDIR)/qt-main.ss --repl 0 &
-	@for i in $$(seq 1 30); do \
-	  [ -f $(HOME)/.jerboa-repl-port ] && break; \
-	  sleep 0.5; \
-	done
-	@if [ ! -f $(HOME)/.jerboa-repl-port ]; then \
-	  echo "ERROR: jemacs-qt failed to start (no REPL port file after 15s)"; exit 1; \
-	fi
-	@PORT=$$(grep -oP '\d+' $(HOME)/.jerboa-repl-port); \
-	echo "jemacs-qt running on REPL port $$PORT"; \
-	$(SCHEME) $(LIBDIRS) --script tests/stress-test.ss --port $$PORT; \
-	STATUS=$$?; \
-	echo ""; \
-	echo "=== Stress test ended ==="; \
-	if [ -f $(HOME)/.jemacs-crash.log ]; then \
-	  echo "=== CRASH LOG ==="; \
-	  cat $(HOME)/.jemacs-crash.log; \
-	fi; \
-	echo "=== STRESS LOG (last 50 lines) ==="; \
-	tail -50 stress-test.log 2>/dev/null; \
-	exit $$STATUS
+# Focused all-in-one stress profiles.
+stress-window: build repl_shim.$(SHLIB_EXT) libqt_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
+	$(STRESS_ENV) scripts/run-stress-profile.sh window interpreted
+
+stress-window-static:
+	$(STRESS_ENV) scripts/run-stress-profile.sh window static
+
+stress-buffer: build repl_shim.$(SHLIB_EXT) libqt_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
+	$(STRESS_ENV) scripts/run-stress-profile.sh buffer interpreted
+
+stress-buffer-static:
+	$(STRESS_ENV) scripts/run-stress-profile.sh buffer static
+
+stress-edit: build repl_shim.$(SHLIB_EXT) libqt_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
+	$(STRESS_ENV) scripts/run-stress-profile.sh edit interpreted
 
-# All-in-one: launch static jemacs-qt under gdb + run stress test driver
+stress-edit-static:
+	$(STRESS_ENV) scripts/run-stress-profile.sh edit static
+
+stress-file: build repl_shim.$(SHLIB_EXT) libqt_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
+	$(STRESS_ENV) scripts/run-stress-profile.sh file interpreted
+
+stress-file-static:
+	$(STRESS_ENV) scripts/run-stress-profile.sh file static
+
+stress-chaos: build repl_shim.$(SHLIB_EXT) libqt_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
+	$(STRESS_ENV) scripts/run-stress-profile.sh chaos interpreted
+
+stress-chaos-static:
+	$(STRESS_ENV) scripts/run-stress-profile.sh chaos static
+
+# Backward-compatible aliases for the historical all-in-one burn-in.
+stress-burn: build repl_shim.$(SHLIB_EXT) libqt_shim.$(SHLIB_EXT) vterm_shim.$(SHLIB_EXT) qt_chez_shim.$(SHLIB_EXT) libjsh-ffi.$(SHLIB_EXT) libjsh_coreutils_stub.$(SHLIB_EXT) $(NATIVE_LIB) $(SSL_SHIM)
+	$(STRESS_ENV) scripts/run-stress-profile.sh chaos interpreted
+
+# Backward-compatible alias for static gdb burn-in.
 stress-burn-static:
-	@echo "=== Starting jemacs-qt (static) stress burn-in under gdb ==="
-	@rm -f $(HOME)/.jerboa-repl-port stress-test.log
-	@xvfb-run -a gdb -batch \
-	  -ex 'handle SIGALRM nostop noprint' \
-	  -ex 'handle SIG34 nostop noprint' \
-	  -ex run \
-	  -ex 'bt full' \
-	  -ex 'thread apply all bt full' \
-	  -ex 'info registers' \
-	  --args ./jemacs-qt --repl 0 &
-	@for i in $$(seq 1 30); do \
-	  [ -f $(HOME)/.jerboa-repl-port ] && break; \
-	  sleep 0.5; \
-	done
-	@if [ ! -f $(HOME)/.jerboa-repl-port ]; then \
-	  echo "ERROR: jemacs-qt failed to start (no REPL port file after 15s)"; exit 1; \
-	fi
-	@PORT=$$(grep -oP '\d+' $(HOME)/.jerboa-repl-port); \
-	echo "jemacs-qt (static) running under gdb on REPL port $$PORT"; \
-	$(SCHEME) $(LIBDIRS) --script tests/stress-test.ss --port $$PORT; \
-	STATUS=$$?; \
-	echo ""; \
-	echo "=== Stress test ended ==="; \
-	if [ -f $(HOME)/.jemacs-crash.log ]; then \
-	  echo "=== CRASH LOG ==="; \
-	  cat $(HOME)/.jemacs-crash.log; \
-	fi; \
-	echo "=== STRESS LOG (last 50 lines) ==="; \
-	tail -50 stress-test.log 2>/dev/null; \
-	exit $$STATUS
+	$(STRESS_ENV) scripts/run-stress-profile.sh chaos static
 
 # =============================================================================
 # Scenario runner — coherent user workflows, screenshots, assertions, hours
diff --git a/build-binary-qt.ss b/build-binary-qt.ss
index 46c6adf..b29ee92 100644
--- a/build-binary-qt.ss
+++ b/build-binary-qt.ss
@@ -15,6 +15,38 @@
 
 (import (chezscheme))
 
+;; Feature flags mirror jerboa-shell's JSH_FEATURES convention:
+;;   ""/"none" -> minimal build, "all" -> all optional features,
+;;   "aws,..." -> selected optional features.
+(define *all-jemacs-features* '(aws))
+
+(define *jemacs-enabled-features*
+  (let ((env (or (getenv "JEMACS_FEATURES") "")))
+    (cond
+      ((or (string=? env "") (string=? env "none")) '())
+      ((string=? env "all") *all-jemacs-features*)
+      (else
+       (let split ((i 0) (start 0) (acc '()))
+         (cond
+           ((= i (string-length env))
+            (let ((s (substring env start i)))
+              (if (string=? s "")
+                  (reverse acc)
+                  (reverse (cons (string->symbol s) acc)))))
+           ((char=? (string-ref env i) #\,)
+            (let ((s (substring env start i)))
+              (split (+ i 1) (+ i 1)
+                     (if (string=? s "")
+                         acc
+                         (cons (string->symbol s) acc)))))
+           (else
+            (split (+ i 1) start acc))))))))
+
+(define (jemacs-feature-enabled? feature)
+  (and (memq feature *jemacs-enabled-features*) #t))
+
+(define aws-enabled? (jemacs-feature-enabled? 'aws))
+
 ;; --- Helper: generate C header from binary file ---
 (define (file->c-header input-path output-path array-name size-name)
   (let* ((port (open-file-input-port input-path))
@@ -140,9 +172,11 @@
 (printf "Sci dir:       ~a~n" sci-dir)
 (printf "Qt dir:        ~a~n" qt-dir)
 (printf "Qt shim dir:   ~a~n" qt-shim-dir)
-(printf "jaws dir:      ~a~n" jaws-dir)
-(printf "chez-ssl dir:  ~a~n" chez-ssl-dir)
-(printf "chez-https dir:~a~n" chez-https-dir)
+(printf "Features:      ~a~n" *jemacs-enabled-features*)
+(when aws-enabled?
+  (printf "jaws dir:      ~a~n" jaws-dir)
+  (printf "chez-ssl dir:  ~a~n" chez-ssl-dir)
+  (printf "chez-https dir:~a~n" chez-https-dir))
 
 ;; --- Step 1: Compile all modules + entry point ---
 (printf "~n[1/7] Compiling all modules (optimize-level 3, WPO)...~n")
@@ -158,6 +192,9 @@
                (debug-level 0)
                (generate-inspector-information #f)
                (generate-wpo-files #t))
+  (when aws-enabled?
+    (printf "  Compiling AWS feature module...~n")
+    (compile-library "lib/jerboa-emacs/qt/commands-aws-native.sls"))
   (compile-program "qt-main.ss"))
 
 ;; --- Step 2: Whole-program optimization ---
@@ -227,7 +264,26 @@
 
 (define (existing-so-files paths)
   (filter file-exists? paths))
+
+(define (aws-feature-so-files)
+  (if aws-enabled?
+      (existing-so-files
+        (append
+          (list
+            "lib/jerboa-emacs/qt/commands-aws-native.so"
+            (format "~a/src/chez-ssl.so" chez-ssl-dir)
+            (format "~a/chez-https.so" chez-https-dir))
+          (map
+            (lambda (m)
+              (format "~a/jerboa-aws/~a.so" jaws-dir m))
+            '("creds" "crypto" "xml" "json" "time" "uri" "sigv4"
+              "request" "api" "ec2/xml" "ec2/params" "ec2/api"
+              "ec2/instances"))))
+      '()))
+
 (let ((boot-so-files (existing-so-files (unique-strings (wpo-missing-so-files)))))
+  (set! boot-so-files
+    (unique-strings (append boot-so-files (aws-feature-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))
@@ -354,15 +410,14 @@ echo OK"
         (display "Error: qt_static_symbols.c compilation failed\n")
         (exit 1)))))
 
-;; jsh FFI shim (needed for static builds and macOS dynamic builds so ffi_* symbols are in the binary)
-;; ffi-shim.c lives in the jsh root (parent of jsh-dir which is the src/ subdir)
-(when (or jemacs-static? macos-build?)
-  (let* ((jsh-root (path-parent jsh-dir))
-         (cmd (format "gcc -c -O2 -o jemacs-qt-jsh-ffi.o ~a/ffi-shim.c -Wall 2>&1"
-                      jsh-root)))
-    (unless (= 0 (system cmd))
-      (display "Error: jsh ffi-shim.c compilation failed\n")
-      (exit 1))))
+;; jsh FFI shim.  Compile this into every binary so jsh/imported editor
+;; modules do not require an external LD_PRELOAD just to resolve ffi_* symbols.
+(let* ((jsh-root (path-parent jsh-dir))
+       (cmd (format "gcc -c -O2 -o jemacs-qt-jsh-ffi.o ~a/ffi-shim.c -Wall 2>&1"
+                    jsh-root)))
+  (unless (= 0 (system cmd))
+    (display "Error: jsh ffi-shim.c compilation failed\n")
+    (exit 1)))
 
 ;; libcoreutils.c (coreutils_raw_mode_*, coreutils_terminal_*, etc.)
 ;; Needed for static builds — provides C symbols referenced by jerboa-coreutils FFI
@@ -386,30 +441,28 @@ echo OK"
 ;; 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))
-         (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))))
+(let* ((jsh-root (path-parent jsh-dir))
+       (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)))
 
 ;; jsh ssh-agent stub (chez_ssh_agent_stop referenced in main.sls but not needed for jemacs)
-(when (or jemacs-static? macos-build?)
-  (let ((stub-file "jemacs-qt-ssh-agent-stub.c"))
-    (call-with-output-file stub-file
-      (lambda (out)
-        (fprintf out "/* Stub — jemacs doesn't use ssh-agent */~n")
-        (fprintf out "void chez_ssh_agent_stop(void) {}~n")
-        (fprintf out "int chez_ssh_agent_is_running(void) { return 0; }~n"))
-      'replace)
-    (let ((cmd (format "gcc -c -O2 -o jemacs-qt-ssh-agent-stub.o ~a -Wall 2>&1" stub-file)))
-      (unless (= 0 (system cmd))
-        (display "Error: ssh-agent stub compilation failed\n")
-        (exit 1)))))
+(let ((stub-file "jemacs-qt-ssh-agent-stub.c"))
+  (call-with-output-file stub-file
+    (lambda (out)
+      (fprintf out "/* Stub — jemacs doesn't use ssh-agent */~n")
+      (fprintf out "void chez_ssh_agent_stop(void) {}~n")
+      (fprintf out "int chez_ssh_agent_is_running(void) { return 0; }~n"))
+    'replace)
+  (let ((cmd (format "gcc -c -O2 -o jemacs-qt-ssh-agent-stub.o ~a -Wall 2>&1" stub-file)))
+    (unless (= 0 (system cmd))
+      (display "Error: ssh-agent stub compilation failed\n")
+      (exit 1))))
 
 ;; chez-scintilla stubs (TUI-only — Qt never calls these; stubs allow foreign-procedure defs)
 (when jemacs-static?
@@ -419,7 +472,7 @@ echo OK"
       (exit 1))))
 
 ;; chez-ssl shim (TLS FFI for jerboa-aws EC2 API calls)
-(when jemacs-static?
+(when (and jemacs-static? aws-enabled?)
   (let* ((cmd (format "gcc -c -O2 -o jemacs-qt-chez-ssl-shim.o ~a/chez_ssl_shim.c -Wall 2>&1"
                       chez-ssl-dir)))
     (unless (= 0 (system cmd))
@@ -578,22 +631,26 @@ grep -v '^$' | grep -v '^register_static_foreign_symbols$'")
                        "/tmp/jemacs-build/crypto_stub.o" ""))
          ;; jsh Rust coreutils static library (musl build, pre-compiled on host)
          (jsh-coreutils-lib (or (getenv "JSH_COREUTILS_LIB") ""))
-         (ssl-libs (let ((pkgconf (shell-output "pkg-config --static --libs openssl 2>/dev/null" "")))
-                     (if (> (string-length pkgconf) 0)
-                       pkgconf
-                       "-L/usr/lib -lssl -lcrypto")))
+         (aws-ssl-obj (if aws-enabled? "jemacs-qt-chez-ssl-shim.o" ""))
+         (ssl-libs (if aws-enabled?
+                       (let ((pkgconf (shell-output "pkg-config --static --libs openssl 2>/dev/null" "")))
+                         (if (> (string-length pkgconf) 0)
+                             pkgconf
+                             "-L/usr/lib -lssl -lcrypto"))
+                       ""))
          (cmd (format "g++ -static -Wl,--export-dynamic -o jemacs-qt \
 jemacs-qt-main.o jemacs-qt-chez-shim.o jemacs-qt-pcre2-shim.o jemacs-qt-jsh-ffi.o \
 jemacs-qt-libcoreutils.o jemacs-qt-jsh-coreutils-stubs.o \
 jemacs-qt-embed-crypto.o jemacs-qt-ssh-agent-stub.o ~a \
 jemacs-qt-pty-shim.o jemacs-qt-vterm-shim.o jemacs-qt-repl-shim.o jemacs-qt-jerboa-landlock.o jemacs-qt-sci-stubs.o \
-jemacs-qt-chez-ssl-shim.o \
+~a \
 qt_static_symbols.o \
 ~a ~a ~a ~a ~a ~a \
 -L~a -lkernel -llz4 -lz \
 ~a \
 -lvterm -lm -ldl -lpthread -luuid -lncurses -lstdc++ 2>&1"
                       crypto-stub
+                      aws-ssl-obj
                       libqt-shim qt-plugins ts-link qt-libs pcre2-libs jsh-coreutils-lib
                       chez-dir ssl-libs)))
     (printf "  ~a~n" cmd)
@@ -627,6 +684,7 @@ jemacs-qt-main.o jemacs-qt-chez-shim.o jemacs-qt-pcre2-shim.o jemacs-qt-jsh-ffi.
              ;; Linux: standard dynamic link
              (format "g++ -rdynamic -o jemacs-qt \
 jemacs-qt-main.o jemacs-qt-chez-shim.o jemacs-qt-pcre2-shim.o \
+jemacs-qt-jsh-ffi.o jemacs-qt-embed-crypto.o jemacs-qt-ssh-agent-stub.o \
 ~a ~a \
 -L~a -lkernel -llz4 -lz -lm -ldl -lpthread -luuid -lncurses -lstdc++ \
 -L. -lqt_shim -lqscintilla2_qt6 -lvterm \
@@ -646,6 +704,9 @@ jemacs-qt-main.o jemacs-qt-chez-shim.o jemacs-qt-pcre2-shim.o \
       "jemacs_qt_program.h" "jemacs_qt_petite_boot.h"
       "jemacs_qt_scheme_boot.h" "jemacs_qt_jemacs_qt_boot.h"
       "jemacs-qt-all.so" "qt-main.so" "qt-main.wpo" "jemacs-qt.boot")
+    '("jemacs-qt-jsh-ffi.o" "jemacs-qt-embed-crypto.o"
+      "jemacs-qt-ssh-agent-stub.o" "jemacs-qt-ssh-agent-stub.c"
+      "qt_static_symbols.o" "qt_static_symbols.c")
     (if jemacs-static?
         '("jemacs-qt-jsh-ffi.o" "jemacs-qt-libcoreutils.o"
           "jemacs-qt-jsh-coreutils-stubs.o"
@@ -653,8 +714,11 @@ jemacs-qt-main.o jemacs-qt-chez-shim.o jemacs-qt-pcre2-shim.o \
           "jemacs-qt-ssh-agent-stub.o" "jemacs-qt-ssh-agent-stub.c"
           "jemacs-qt-pty-shim.o" "jemacs-qt-vterm-shim.o"
           "jemacs-qt-jerboa-landlock.o"
-          "jemacs-qt-sci-stubs.o" "jemacs-qt-chez-ssl-shim.o"
+          "jemacs-qt-sci-stubs.o"
           "qt_static_symbols.o" "qt_static_symbols.c")
+        '())
+    (if (and jemacs-static? aws-enabled?)
+        '("jemacs-qt-chez-ssl-shim.o")
         '())))
 
 (printf "~n========================================~n")
diff --git a/lib/jerboa-emacs/debug-repl.sls b/lib/jerboa-emacs/debug-repl.sls
index d4f4b93..082896d 100644
--- a/lib/jerboa-emacs/debug-repl.sls
+++ b/lib/jerboa-emacs/debug-repl.sls
@@ -27,7 +27,10 @@
   (def *repl-protocol* 'unknown)
   (def *repl-unknown-ticks* 0)
   (def *repl-port-file*
-       (string-append (getenv "HOME") "/.jerboa-repl-port"))
+       (or (getenv "JEMACS_REPL_PORT_FILE" #f)
+           (string-append
+             (getenv "HOME" "/tmp")
+             "/.jerboa-repl-port")))
   (def *repl-env* (interaction-environment))
   (def (debug-repl-bind! name value)
        "Register a binding in the debug REPL environment so it's accessible via IPC.\n   Uses Chez's define-top-level-value to inject the value directly."
diff --git a/lib/jerboa-emacs/qt/app.sls b/lib/jerboa-emacs/qt/app.sls
index 97afd0e..7efde05 100644
--- a/lib/jerboa-emacs/qt/app.sls
+++ b/lib/jerboa-emacs/qt/app.sls
@@ -2465,6 +2465,7 @@
                 (cons 'app-state-echo app-state-echo)
                 (cons 'qt-current-editor qt-current-editor)
                 (cons 'qt-current-buffer qt-current-buffer)
+                (cons 'qt-validate-window-tree! qt-validate-window-tree!)
                 (cons
                   'qt-plain-text-edit-cursor-position
                   qt-plain-text-edit-cursor-position)
diff --git a/lib/jerboa-emacs/qt/commands-aliases.sls b/lib/jerboa-emacs/qt/commands-aliases.sls
index 95dfe0f..476ab6c 100644
--- a/lib/jerboa-emacs/qt/commands-aliases.sls
+++ b/lib/jerboa-emacs/qt/commands-aliases.sls
@@ -1121,6 +1121,7 @@
    (register-command! 'vterm-copy-mode cmd-vterm-copy-mode)
    (register-command! 'vterm-copy-done cmd-vterm-copy-done)
    (register-command! 'lsp cmd-toggle-lsp)
+   (register-command! 'lsp-start cmd-toggle-lsp)
    (register-command!
      'lsp-goto-definition
      cmd-lsp-goto-definition)
diff --git a/lib/jerboa-emacs/qt/commands-aws-native.sls b/lib/jerboa-emacs/qt/commands-aws-native.sls
new file mode 100644
index 0000000..836faff
--- /dev/null
+++ b/lib/jerboa-emacs/qt/commands-aws-native.sls
@@ -0,0 +1,428 @@
+#!chezscheme
+;;; Generated by jerbuild — DO NOT EDIT
+;;; Source: src/jerboa-emacs/qt/commands-aws-native.ss
+
+(library (jerboa-emacs qt commands-aws-native)
+  (export cmd-aws-ec2-ssh cmd-aws-ec2-ssh-connect
+    cmd-aws-ec2-ssh-refresh cmd-aws-ec2-ssh-force-refresh
+    cmd-aws-ec2-ssh-filter cmd-aws-ec2-ssh-clear-filter
+    cmd-aws-ec2-ssh-sort-name cmd-aws-ec2-ssh-sort-region
+    aws-ec2-ssh-setup-mode!)
+  (import
+   (except (chezscheme) make-hash-table hash-table? iota \x31;+ \x31;-
+     getenv path-extension path-absolute? thread? make-mutex
+     mutex? mutex-name sort sort!)
+   (std sugar) (std sort) (std srfi srfi-13)
+   (only (std misc string) string-empty?)
+   (only (std misc ports) read-file-lines)
+   (chez-scintilla constants) (jerboa-emacs core)
+   (jerboa-emacs buffer) (jerboa-emacs tabulated-list)
+   (jerboa-emacs terminal) (jerboa-emacs async)
+   (jerboa-emacs echo) (jerboa-emacs qt buffer)
+   (jerboa-emacs qt window) (jerboa-emacs qt sci-shim)
+   (jerboa-emacs qt echo) (jerboa-emacs qt commands-core)
+   (jerboa-aws ec2 api) (jerboa-aws ec2 instances)
+   (jerboa core) (jerboa runtime))
+  (def *aws-ec2-ssh-config-file* "~/.aws-custom-ssh.yaml")
+  (def *aws-ec2-ssh-cache-ttl* 300)
+  (def *aws-ec2-ssh-user* #f)
+  (def *aws-ec2-ssh-common-regions*
+       '("us-east-1" "us-east-2" "us-west-1" "us-west-2" "eu-west-1" "eu-west-2"
+          "eu-west-3" "eu-central-1" "eu-north-1" "ap-northeast-1"
+          "ap-northeast-2" "ap-southeast-1" "ap-southeast-2"
+          "ap-south-1" "sa-east-1" "ca-central-1"))
+  (def *aws-region-domain-map* '())
+  (def *aws-cache* #f)
+  (def *aws-cache-expiry* 0)
+  (def *aws-columns*
+       (list (make-tl-column "Name" 25) (make-tl-column "State" 10)
+         (make-tl-column "Type" 14) (make-tl-column "Private IP" 16)
+         (make-tl-column "Region" 14)
+         (make-tl-column "SSH Target" 40)))
+  (def (aws-load-config!)
+       "Load region->domain mappings from config file."
+       (let ([path (path-expand *aws-ec2-ssh-config-file*)])
+         (if (file-exists? path)
+             (begin
+               (set! *aws-region-domain-map*
+                 (with-catch
+                   (lambda (e) '())
+                   (lambda ()
+                     (let ([lines (read-file-lines path)])
+                       (filter-map
+                         (lambda (line)
+                           (let ([trimmed (string-trim line)])
+                             (and (> (string-length trimmed) 0)
+                                  (not (string-prefix? "#" trimmed))
+                                  (string-contains trimmed ":")
+                                  (let* ([idx (string-contains
+                                                trimmed
+                                                ":")]
+                                         [key (string-trim
+                                                (substring trimmed 0 idx))]
+                                         [val (string-trim
+                                                (substring
+                                                  trimmed
+                                                  (+ idx 1)
+                                                  (string-length
+                                                    trimmed)))])
+                                    (and (> (string-length key) 0)
+                                         (> (string-length val) 0)
+                                         (cons key val))))))
+                         lines)))))
+               (length *aws-region-domain-map*))
+             (begin (set! *aws-region-domain-map* '()) 0))))
+  (def (aws-get-domain region)
+       "Get domain suffix for REGION from config, or #f."
+       (let ([pair (assoc region *aws-region-domain-map*)])
+         (and pair (cdr pair))))
+  (def (aws-cache-valid?)
+       (and *aws-cache*
+            (> *aws-cache-expiry* (time-second (current-time)))))
+  (def (aws-cache-put! instances)
+       (set! *aws-cache* instances)
+       (set! *aws-cache-expiry*
+         (+ (time-second (current-time)) *aws-ec2-ssh-cache-ttl*)))
+  (def (aws-cache-clear!)
+       (set! *aws-cache* #f)
+       (set! *aws-cache-expiry* 0))
+  (def (native-ht-ref ht key default)
+       "Hashtable-ref for native Chez symbol-keyed hashtables from jerboa-aws."
+       (if (hashtable? ht) (hashtable-ref ht key default) default))
+  (def (native-instance-state inst)
+       "Get state name (running, stopped, etc.) from native instance hash."
+       (let ([state (native-ht-ref inst 'instanceState #f)])
+         (if state (or (native-ht-ref state 'name #f) "-") "-")))
+  (def (native-instance-name inst)
+       "Get Name tag value from native instance hash."
+       (let ([tags (native-ht-ref inst 'tagSet '())])
+         (if (list? tags)
+             (let loop ([ts tags])
+               (if (null? ts)
+                   ""
+                   (let ([tag (car ts)])
+                     (if (and (hashtable? tag)
+                              (equal? (native-ht-ref tag 'key #f) "Name"))
+                         (or (native-ht-ref tag 'value #f) "")
+                         (loop (cdr ts))))))
+             "")))
+  (def (native-parse-instances response region)
+       "Parse describe-instances response hash into list of (cons region instance-hash).\n   Only returns running instances."
+       (with-catch
+         (lambda (e) '())
+         (lambda ()
+           (let ([reservations (or (native-ht-ref
+                                     response
+                                     'reservationSet
+                                     #f)
+                                   '())])
+             (apply
+               append
+               (map (lambda (reservation)
+                      (if (hashtable? reservation)
+                          (let ([instances (or (native-ht-ref
+                                                 reservation
+                                                 'instancesSet
+                                                 #f)
+                                               '())])
+                            (if (list? instances)
+                                (filter-map
+                                  (lambda (inst)
+                                    (and (hashtable? inst)
+                                         (string=?
+                                           (native-instance-state inst)
+                                           "running")
+                                         (cons region inst)))
+                                  instances)
+                                '()))
+                          '()))
+                    (if (list? reservations) reservations '())))))))
+  (def (native-instance->entry region inst)
+       "Convert native instance hash + region to a tabulated-list entry."
+       (let* ([id (or (native-ht-ref inst 'instanceId #f) "")]
+              [name (native-instance-name inst)]
+              [state (native-instance-state inst)]
+              [type (or (native-ht-ref inst 'instanceType #f) "-")]
+              [ip (or (native-ht-ref inst 'privateIpAddress #f) "-")]
+              [domain (aws-get-domain region)]
+              [ssh-target (if (and (> (string-length name) 0) domain)
+                              (string-append name "." domain)
+                              "-")])
+         (cons id (vector name state type ip region ssh-target))))
+  (def *aws-pending-regions* 0)
+  (def *aws-pending-instances* '())
+  (def *aws-pending-errors* 0)
+  (def *aws-pending-callback* #f)
+  (def (aws-fetch-all-regions! callback)
+       "Fetch instances from all configured regions asynchronously via native API.\n   Spawns one worker thread per region; results are merged on the UI thread."
+       (let ([regions *aws-ec2-ssh-common-regions*])
+         (set! *aws-pending-regions* (length regions))
+         (set! *aws-pending-instances* '())
+         (set! *aws-pending-errors* 0)
+         (set! *aws-pending-callback* callback)
+         (for-each
+           (lambda (region)
+             (spawn-worker
+               'aws-fetch-region
+               (lambda ()
+                 (with-catch
+                   (lambda (e)
+                     (ui-queue-push!
+                       (lambda ()
+                         (set! *aws-pending-errors*
+                           (+ *aws-pending-errors* 1))
+                         (set! *aws-pending-regions*
+                           (- *aws-pending-regions* 1))
+                         (aws-check-fetch-complete!))))
+                   (lambda ()
+                     (let* ([client (EC2Client 'region: region)]
+                            [result (describe-instances client)]
+                            [running (native-parse-instances
+                                       result
+                                       region)])
+                       (ui-queue-push!
+                         (lambda ()
+                           (set! *aws-pending-instances*
+                             (append *aws-pending-instances* running))
+                           (set! *aws-pending-regions*
+                             (- *aws-pending-regions* 1))
+                           (aws-check-fetch-complete!))))))))
+             regions))))
+  (def (aws-check-fetch-complete!)
+       "Check if all region fetches are done; fire callback when complete."
+       (when (= *aws-pending-regions* 0)
+         (let ([instances *aws-pending-instances*]
+               [cb *aws-pending-callback*])
+           (aws-cache-put! instances)
+           (when cb (cb instances)))))
+  (def (aws-ec2-ssh-setup-mode!)
+       "Register the AWS EC2 SSH mode keymap and buffer-name mapping."
+       (hash-put!
+         *buffer-name-mode-map*
+         "*AWS EC2 SSH*"
+         'aws-ec2-ssh)
+       (let ([km (make-keymap)])
+         (for-each