tools: switch bash/external-generated-code to async aproc; gemini --resume latest

ober

c055decea313b2dc3962b12f995a3ef8a491f891

diff --git a/build-binary.ss b/build-binary.ss
index 58aec48..f13d7c2 100644
--- a/build-binary.ss
+++ b/build-binary.ss
@@ -326,6 +326,7 @@
       "std/os/platform"
       "std/os/path"
       "std/os/shell"
+      "std/os/aproc"
       "std/os/sysmon"
       "std/security/capsicum"
       "std/os/sandbox"
diff --git a/src/jcode/tool/bash.ss b/src/jcode/tool/bash.ss
index 09e01fa..12542bb 100644
--- a/src/jcode/tool/bash.ss
+++ b/src/jcode/tool/bash.ss
@@ -2,7 +2,7 @@
 
 (export init-bash-tool)
 
-(import :std/os/shell
+(import :std/os/aproc
         :std/misc/string
         :jcode/core/log
         :jcode/core/permissions
@@ -56,9 +56,14 @@
          (run-bash-command command timeout cwd))))))
 
 (def (run-bash-command command timeout cwd)
+  ;; aproc-run/status is __collect_safe under the hood, so a long-running
+  ;; bash tool call (e.g. `make build`) doesn't pin the TC mutex and the
+  ;; TUI keeps rendering. shell/status — which it replaces — read through
+  ;; Chez ports and froze every other green thread for the subprocess's
+  ;; lifetime.
   (let ((cmd (sandbox-wrap-command command cwd)))
     (try
-      (let-values (((stdout stderr exit-code) (shell/status cmd cwd)))
+      (let-values (((stdout stderr exit-code) (aproc-run/status cmd cwd)))
         (format-result stdout stderr exit-code))
       (catch (e)
         (format "Error: ~a" (err->string e))))))
diff --git a/src/jcode/tool/external-llm.ss b/src/jcode/tool/external-llm.ss
index 573df2a..3f5ee65 100644
--- a/src/jcode/tool/external-llm.ss
+++ b/src/jcode/tool/external-llm.ss
@@ -277,12 +277,16 @@
                parse-claude-json
                eff-sid))))
     ((gemini)
+     ;; gemini --resume only accepts "latest" or a numeric history index
+     ;; (NOT a UUID), so we resume by name rather than by self-assigned
+     ;; UUID. eff-sid is still tracked so ext-result has something stable
+     ;; to return to the caller.
      (let ((resume? (nonempty-string session-id)))
        (let ((eff-sid (or resume? (make-external-session-id))))
          (list "gemini"
                (append (list "gemini" "-p" prompt)
                        (if resume?
-                         (list "--resume" eff-sid)
+                         (list "--resume" "latest")
                          (list "--session-id" eff-sid))
                        (list "-o" "json"
                              "--yolo" "--skip-trust"))