diff --git a/docs/launcher-contract.md b/docs/launcher-contract.md
index e37cb264..a0d4208f 100644
--- a/docs/launcher-contract.md
+++ b/docs/launcher-contract.md
@@ -108,3 +108,52 @@ command from a caller-supplied working directory. Called as
prints `Missing host working directory:
` to stderr and exits `2`. With no
command arguments it is a no-op returning `0`. `HOME` resolution and the pinned
`PATH`/locale are identical to `run_clean_host_command()`.
+
+## Go/Colima host-utility wrappers (`go-hostutil.sh`)
+
+`scripts/lib/launcher/go-hostutil.sh` invokes the `workcell-hostutil` and
+`workcell-colimautil` Go programs on the host via `go run`, always routed
+through `run_clean_host_command_in_dir` (from `host-exec.sh`) so the child
+executes from `${ROOT_DIR}` under the sanitised `env -i` host environment. Every
+helper depends only on `ensure_go_run_env` plus the `GOPATH`/`GOMODCACHE`/
+`GOCACHE` it exports (`scripts/lib/go-run-env.sh`),
+`run_clean_host_command_in_dir` (`scripts/lib/launcher/host-exec.sh`), and the
+`ROOT_DIR` global set in `scripts/workcell`. `HOST_GO_BIN` is resolved by this
+module itself (via `resolve_fixed_host_tool` from `host-exec.sh`, sourced
+immediately before), since these wrappers are its sole consumer — so every
+dependency is sourced or assigned before the first wrapper call, which makes the
+module self-contained.
+
+### `go_hostutil()`
+
+Runs `workcell-hostutil` on the host. Calls `ensure_go_run_env`, then executes
+`"${HOST_GO_BIN}" run ./cmd/workcell-hostutil "$@"` from `${ROOT_DIR}` via
+`run_clean_host_command_in_dir`, forwarding only `GOPATH`/`GOMODCACHE`/`GOCACHE`
+into the sanitised environment. All other host context must be passed on argv
+because the `env -i` boundary strips inherited environment variables.
+
+### `run_go_hostutil_preserve_exit()`
+
+Wraps `go_hostutil()` and recovers the Go child's real exit code. It captures
+the child's stderr to a temp file (cleaned up via a `RETURN` trap and
+explicitly), and if the stderr ends in an `exit status N` trailer emitted by
+`go run`, it substitutes `N` for the generic exit code `1` and strips the
+trailer from the forwarded stderr. Non-trailer stderr is re-emitted unchanged
+and the resolved exit code is returned.
+
+### `go_hostutil_publish_pr()`
+
+Same `go run ./cmd/workcell-hostutil` invocation as `go_hostutil()`, but forwards
+an explicit allowlist of terminal, GnuPG, SSH, XDG, and GitHub environment
+variables (for example `TERM`, `GPG_TTY`, `GNUPGHOME`, `SSH_AUTH_SOCK`,
+`GIT_ASKPASS`, the `XDG_*` dirs, `GH_TOKEN`/`GITHUB_TOKEN`, `GH_HOST`,
+`GH_CONFIG_DIR`) — each added only when non-empty — so host-side PR publication
+can reach the operator's credentials and interactive signing agents while the
+rest of the environment stays sanitised.
+
+### `go_colimautil()`
+
+Runs `workcell-colimautil` on the host. Identical structure to `go_hostutil()`
+(`ensure_go_run_env`, forwarding `GOPATH`/`GOMODCACHE`/`GOCACHE` from
+`${ROOT_DIR}` via `run_clean_host_command_in_dir`), targeting
+`./cmd/workcell-colimautil` instead.
diff --git a/internal/metadatautil/core.go b/internal/metadatautil/core.go
index 9f8b62ee..4a1c6d65 100644
--- a/internal/metadatautil/core.go
+++ b/internal/metadatautil/core.go
@@ -469,6 +469,7 @@ func GenerateControlPlaneManifest(rootDir, outputPath string) error {
"scripts/lib/extract_direct_mounts",
"scripts/lib/launcher/host-detect.sh",
"scripts/lib/launcher/host-exec.sh",
+ "scripts/lib/launcher/go-hostutil.sh",
"scripts/lib/render_injection_bundle",
"scripts/lib/sessionctl-shim.sh",
"scripts/lib/shellproto.sh",
diff --git a/internal/testkit/security_boundary_test.go b/internal/testkit/security_boundary_test.go
index aaede920..f290999d 100644
--- a/internal/testkit/security_boundary_test.go
+++ b/internal/testkit/security_boundary_test.go
@@ -185,15 +185,30 @@ func TestWorkcellBootstrapResolvesRealHomeBeforeGoHostutil(t *testing.T) {
t.Fatalf("%s exports WORKCELL_GO_CACHE_ROOT before REAL_HOME is resolved", scriptPath)
}
- goHostutilIndex := strings.Index(script, `go_hostutil() {`)
- if goHostutilIndex == -1 {
- t.Fatalf("%s must define go_hostutil", scriptPath)
+ // go_hostutil now lives in scripts/lib/launcher/go-hostutil.sh, so it
+ // becomes defined at the point scripts/workcell sources that module. The
+ // ordering invariant therefore targets the source line: the module must be
+ // sourced only after REAL_HOME is resolved and WORKCELL_GO_CACHE_ROOT is
+ // exported, so the go_hostutil/go_colimautil wrappers can never run with an
+ // unsanitised host home or Go cache root.
+ goHostutilSourceIndex := strings.Index(script, `source "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh"`)
+ if goHostutilSourceIndex == -1 {
+ t.Fatalf("%s must source scripts/lib/launcher/go-hostutil.sh", scriptPath)
}
- if realHomeIndex > goHostutilIndex {
- t.Fatalf("%s resolves REAL_HOME after go_hostutil is defined; want bootstrap home resolved first", scriptPath)
+ if realHomeIndex > goHostutilSourceIndex {
+ t.Fatalf("%s resolves REAL_HOME after go-hostutil.sh is sourced; want bootstrap home resolved first", scriptPath)
}
- if cacheRootIndex > goHostutilIndex {
- t.Fatalf("%s exports WORKCELL_GO_CACHE_ROOT after go_hostutil is defined; want cache root fixed first", scriptPath)
+ if cacheRootIndex > goHostutilSourceIndex {
+ t.Fatalf("%s exports WORKCELL_GO_CACHE_ROOT after go-hostutil.sh is sourced; want cache root fixed first", scriptPath)
+ }
+
+ modulePath := filepath.Join(repoRoot(t), "scripts", "lib", "launcher", "go-hostutil.sh")
+ moduleContent, err := os.ReadFile(modulePath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !strings.Contains(string(moduleContent), `go_hostutil() {`) {
+ t.Fatalf("%s must define go_hostutil", modulePath)
}
}
diff --git a/runtime/container/control-plane-manifest.json b/runtime/container/control-plane-manifest.json
index 83cccd83..e0f21b75 100644
--- a/runtime/container/control-plane-manifest.json
+++ b/runtime/container/control-plane-manifest.json
@@ -2,7 +2,7 @@
"host_artifacts": [
{
"repo_path": "scripts/workcell",
- "sha256": "8cad3d7c2f99071a346a478a45915c6a3ff2997c94133c6c8384e3893b79eec3"
+ "sha256": "6e9c2fa71b8b1c5f971a710c9e4e33769bcf2210a61ab2c8f1420caebeedf002"
},
{
"repo_path": "scripts/check-publish-commit-signatures.sh",
@@ -20,6 +20,10 @@
"repo_path": "scripts/lib/launcher/host-exec.sh",
"sha256": "475bfcf95c6e3d20631ba2aacd43261fa116323191b1898a47afbf35c96fbd50"
},
+ {
+ "repo_path": "scripts/lib/launcher/go-hostutil.sh",
+ "sha256": "775d3dd6e5d946229d6eb38ccfcc36f6a89711662c4fcd2df9d097a8741e0116"
+ },
{
"repo_path": "scripts/lib/render_injection_bundle",
"sha256": "f1057951d6f65e12d82a7bc2b5002afde5664670d8f4ed7d9bc289bbec5f5901"
diff --git a/scripts/dev-quick-check.sh b/scripts/dev-quick-check.sh
index 6c8edc82..7f821140 100755
--- a/scripts/dev-quick-check.sh
+++ b/scripts/dev-quick-check.sh
@@ -52,6 +52,7 @@ shell_files=(
"${ROOT_DIR}/scripts/lib/go-run-env.sh"
"${ROOT_DIR}/scripts/lib/launcher/host-detect.sh"
"${ROOT_DIR}/scripts/lib/launcher/host-exec.sh"
+ "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh"
"${ROOT_DIR}/scripts/lib/manage_injection_policy"
"${ROOT_DIR}/scripts/lib/pty_transcript"
"${ROOT_DIR}/scripts/lib/render_injection_bundle"
diff --git a/scripts/lib/launcher/go-hostutil.sh b/scripts/lib/launcher/go-hostutil.sh
new file mode 100755
index 00000000..60081930
--- /dev/null
+++ b/scripts/lib/launcher/go-hostutil.sh
@@ -0,0 +1,105 @@
+#!/usr/bin/env -S BASH_ENV= ENV= bash
+# shellcheck shell=bash
+# SPDX-License-Identifier: Apache-2.0
+# Copyright 2026 Omkhar Arasaratnam
+#
+# scripts/lib/launcher/go-hostutil.sh — Go/Colima host-utility wrapper
+# module extracted from scripts/workcell as the next increment of the
+# launcher decomposition (roadmap item D4). These helpers invoke the
+# workcell-hostutil and workcell-colimautil Go programs on the host via
+# `go run`, always routed through run_clean_host_command_in_dir so the
+# child executes from ${ROOT_DIR} under the sanitised host environment
+# (env -i with a pinned PATH/HOME and C locale) provided by
+# scripts/lib/launcher/host-exec.sh. They depend only on
+# ensure_go_run_env plus the GOPATH/GOMODCACHE/GOCACHE it exports
+# (scripts/lib/go-run-env.sh), run_clean_host_command_in_dir
+# (scripts/lib/launcher/host-exec.sh), and the readonly ROOT_DIR global
+# set in scripts/workcell — all sourced or assigned before the first
+# wrapper call — so they are a self-contained, behaviour-preserving unit.
+# HOST_GO_BIN is resolved by this module (below) since it is the sole
+# consumer; resolve_fixed_host_tool comes from the host-exec.sh module
+# sourced immediately before this one.
+# run_go_hostutil_preserve_exit additionally
+# recovers the Go child's real exit code from its `exit status N` stderr
+# trailer. go_hostutil_publish_pr forwards an explicit allowlist of
+# terminal/GnuPG/SSH/XDG/GitHub environment variables (read at call time)
+# so host-side PR publication can reach the operator's credentials. See
+# docs/launcher-contract.md for the module contract.
+
+HOST_GO_BIN="$(resolve_fixed_host_tool go /opt/homebrew/bin/go /usr/local/go/bin/go /usr/local/bin/go /usr/bin/go)"
+
+go_hostutil() {
+ ensure_go_run_env
+ run_clean_host_command_in_dir "${ROOT_DIR}" env \
+ GOPATH="${GOPATH}" \
+ GOMODCACHE="${GOMODCACHE}" \
+ GOCACHE="${GOCACHE}" \
+ "${HOST_GO_BIN}" run ./cmd/workcell-hostutil "$@"
+}
+
+run_go_hostutil_preserve_exit() {
+ local stderr_file=""
+ local stderr_capture=""
+ local rc=0
+
+ stderr_file="$(mktemp "${TMPDIR:-/tmp}/workcell-hostutil-stderr.XXXXXX")"
+ trap 'rm -f "${stderr_file}"' RETURN
+ go_hostutil "$@" 2>"${stderr_file}" || rc=$?
+ stderr_capture="$(cat "${stderr_file}")"
+ rm -f "${stderr_file}"
+ trap - RETURN
+
+ if [[ "${stderr_capture}" =~ (^|$'\n')exit\ status\ ([0-9]+)$ ]]; then
+ if [[ ${rc} -eq 1 ]]; then
+ rc="${BASH_REMATCH[2]}"
+ fi
+ if [[ -z "${BASH_REMATCH[1]}" ]]; then
+ stderr_capture=""
+ else
+ stderr_capture="${stderr_capture%$'\n'exit status [0-9]*}"
+ fi
+ fi
+ if [[ -n "${stderr_capture}" ]]; then
+ printf '%s\n' "${stderr_capture}" >&2
+ fi
+ return "${rc}"
+}
+
+go_hostutil_publish_pr() {
+ ensure_go_run_env
+ local -a env_args=(
+ "GOPATH=${GOPATH}"
+ "GOMODCACHE=${GOMODCACHE}"
+ "GOCACHE=${GOCACHE}"
+ )
+
+ [[ -n "${TERM:-}" ]] && env_args+=("TERM=${TERM}")
+ [[ -n "${GPG_TTY:-}" ]] && env_args+=("GPG_TTY=${GPG_TTY}")
+ [[ -n "${GNUPGHOME:-}" ]] && env_args+=("GNUPGHOME=${GNUPGHOME}")
+ [[ -n "${SSH_AUTH_SOCK:-}" ]] && env_args+=("SSH_AUTH_SOCK=${SSH_AUTH_SOCK}")
+ [[ -n "${SSH_AGENT_PID:-}" ]] && env_args+=("SSH_AGENT_PID=${SSH_AGENT_PID}")
+ [[ -n "${SSH_ASKPASS:-}" ]] && env_args+=("SSH_ASKPASS=${SSH_ASKPASS}")
+ [[ -n "${GIT_ASKPASS:-}" ]] && env_args+=("GIT_ASKPASS=${GIT_ASKPASS}")
+ [[ -n "${XDG_CONFIG_HOME:-}" ]] && env_args+=("XDG_CONFIG_HOME=${XDG_CONFIG_HOME}")
+ [[ -n "${XDG_STATE_HOME:-}" ]] && env_args+=("XDG_STATE_HOME=${XDG_STATE_HOME}")
+ [[ -n "${XDG_CACHE_HOME:-}" ]] && env_args+=("XDG_CACHE_HOME=${XDG_CACHE_HOME}")
+ [[ -n "${XDG_DATA_HOME:-}" ]] && env_args+=("XDG_DATA_HOME=${XDG_DATA_HOME}")
+ [[ -n "${XDG_RUNTIME_DIR:-}" ]] && env_args+=("XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR}")
+ [[ -n "${GH_TOKEN:-}" ]] && env_args+=("GH_TOKEN=${GH_TOKEN}")
+ [[ -n "${GITHUB_TOKEN:-}" ]] && env_args+=("GITHUB_TOKEN=${GITHUB_TOKEN}")
+ [[ -n "${GH_HOST:-}" ]] && env_args+=("GH_HOST=${GH_HOST}")
+ [[ -n "${GH_CONFIG_DIR:-}" ]] && env_args+=("GH_CONFIG_DIR=${GH_CONFIG_DIR}")
+
+ run_clean_host_command_in_dir "${ROOT_DIR}" env \
+ "${env_args[@]}" \
+ "${HOST_GO_BIN}" run ./cmd/workcell-hostutil "$@"
+}
+
+go_colimautil() {
+ ensure_go_run_env
+ run_clean_host_command_in_dir "${ROOT_DIR}" env \
+ GOPATH="${GOPATH}" \
+ GOMODCACHE="${GOMODCACHE}" \
+ GOCACHE="${GOCACHE}" \
+ "${HOST_GO_BIN}" run ./cmd/workcell-colimautil "$@"
+}
diff --git a/scripts/validate-repo.sh b/scripts/validate-repo.sh
index 3929eb25..e2fb6d22 100755
--- a/scripts/validate-repo.sh
+++ b/scripts/validate-repo.sh
@@ -157,6 +157,7 @@ shell_files=(
"${ROOT_DIR}/scripts/lib/go-run-env.sh"
"${ROOT_DIR}/scripts/lib/launcher/host-detect.sh"
"${ROOT_DIR}/scripts/lib/launcher/host-exec.sh"
+ "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh"
"${ROOT_DIR}/scripts/lib/trusted-entrypoint.sh"
"${ROOT_DIR}/scripts/lib/manage_injection_policy"
"${ROOT_DIR}/scripts/lib/pty_transcript"
diff --git a/scripts/verify-invariants.sh b/scripts/verify-invariants.sh
index 3963dcaf..01b0a114 100755
--- a/scripts/verify-invariants.sh
+++ b/scripts/verify-invariants.sh
@@ -2766,7 +2766,7 @@ WORKCELL_COLIMA_TIMEOUT_HARNESS="${BARRIER_VERIFY_ROOT}/workcell-colima-timeout-
printf '\n'
extract_top_level_bash_function "${ROOT_DIR}/scripts/workcell" terminate_process_tree_by_pid
printf '\n'
- extract_top_level_bash_function "${ROOT_DIR}/scripts/workcell" run_go_hostutil_preserve_exit
+ extract_top_level_bash_function "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh" run_go_hostutil_preserve_exit
printf '\n'
extract_top_level_bash_function "${ROOT_DIR}/scripts/workcell" run_host_colima_with_timeout
printf '\n'
@@ -2843,12 +2843,12 @@ WORKCELL_RUNTIME_BUILD_RETRY_HARNESS="${BARRIER_VERIFY_ROOT}/workcell-runtime-bu
} >"${WORKCELL_RUNTIME_BUILD_RETRY_HARNESS}"
bash "${WORKCELL_RUNTIME_BUILD_RETRY_HARNESS}"
-if ! rg -q 'run_clean_host_command_in_dir "\$\{ROOT_DIR\}" env' "${ROOT_DIR}/scripts/workcell" ||
- ! rg -q 'GOPATH="\$\{GOPATH\}"' "${ROOT_DIR}/scripts/workcell" ||
- ! rg -q 'GOMODCACHE="\$\{GOMODCACHE\}"' "${ROOT_DIR}/scripts/workcell" ||
- ! rg -q 'GOCACHE="\$\{GOCACHE\}"' "${ROOT_DIR}/scripts/workcell" ||
- ! rg -q '"\$\{HOST_GO_BIN\}" run ./cmd/workcell-hostutil "\$@"' "${ROOT_DIR}/scripts/workcell"; then
- echo "Expected scripts/workcell to invoke the bootstrap Go helper from the repo root under a scrubbed environment with explicit Go caches" >&2
+if ! rg -q 'run_clean_host_command_in_dir "\$\{ROOT_DIR\}" env' "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh" ||
+ ! rg -q 'GOPATH="\$\{GOPATH\}"' "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh" ||
+ ! rg -q 'GOMODCACHE="\$\{GOMODCACHE\}"' "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh" ||
+ ! rg -q 'GOCACHE="\$\{GOCACHE\}"' "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh" ||
+ ! rg -q '"\$\{HOST_GO_BIN\}" run ./cmd/workcell-hostutil "\$@"' "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh"; then
+ echo "Expected scripts/lib/launcher/go-hostutil.sh to invoke the bootstrap Go helper from the repo root under a scrubbed environment with explicit Go caches" >&2
exit 1
fi
diff --git a/scripts/workcell b/scripts/workcell
index 745fa925..b867ab6a 100755
--- a/scripts/workcell
+++ b/scripts/workcell
@@ -68,7 +68,6 @@ source "${ROOT_DIR}/scripts/lib/sessionctl-shim.sh"
source "${ROOT_DIR}/scripts/lib/launcher/host-detect.sh"
# shellcheck source=/dev/null
source "${ROOT_DIR}/scripts/lib/launcher/host-exec.sh"
-HOST_GO_BIN="$(resolve_fixed_host_tool go /opt/homebrew/bin/go /usr/local/go/bin/go /usr/local/bin/go /usr/bin/go)"
REAL_HOME="$(resolve_workcell_real_home)"
case "$(uname -s 2>/dev/null || true)" in
Darwin)
@@ -78,81 +77,12 @@ case "$(uname -s 2>/dev/null || true)" in
export WORKCELL_GO_CACHE_ROOT="${XDG_CACHE_HOME:-${REAL_HOME}/.cache}/workcell/go"
;;
esac
-go_hostutil() {
- ensure_go_run_env
- run_clean_host_command_in_dir "${ROOT_DIR}" env \
- GOPATH="${GOPATH}" \
- GOMODCACHE="${GOMODCACHE}" \
- GOCACHE="${GOCACHE}" \
- "${HOST_GO_BIN}" run ./cmd/workcell-hostutil "$@"
-}
-
-run_go_hostutil_preserve_exit() {
- local stderr_file=""
- local stderr_capture=""
- local rc=0
-
- stderr_file="$(mktemp "${TMPDIR:-/tmp}/workcell-hostutil-stderr.XXXXXX")"
- trap 'rm -f "${stderr_file}"' RETURN
- go_hostutil "$@" 2>"${stderr_file}" || rc=$?
- stderr_capture="$(cat "${stderr_file}")"
- rm -f "${stderr_file}"
- trap - RETURN
-
- if [[ "${stderr_capture}" =~ (^|$'\n')exit\ status\ ([0-9]+)$ ]]; then
- if [[ ${rc} -eq 1 ]]; then
- rc="${BASH_REMATCH[2]}"
- fi
- if [[ -z "${BASH_REMATCH[1]}" ]]; then
- stderr_capture=""
- else
- stderr_capture="${stderr_capture%$'\n'exit status [0-9]*}"
- fi
- fi
- if [[ -n "${stderr_capture}" ]]; then
- printf '%s\n' "${stderr_capture}" >&2
- fi
- return "${rc}"
-}
-
-go_hostutil_publish_pr() {
- ensure_go_run_env
- local -a env_args=(
- "GOPATH=${GOPATH}"
- "GOMODCACHE=${GOMODCACHE}"
- "GOCACHE=${GOCACHE}"
- )
-
- [[ -n "${TERM:-}" ]] && env_args+=("TERM=${TERM}")
- [[ -n "${GPG_TTY:-}" ]] && env_args+=("GPG_TTY=${GPG_TTY}")
- [[ -n "${GNUPGHOME:-}" ]] && env_args+=("GNUPGHOME=${GNUPGHOME}")
- [[ -n "${SSH_AUTH_SOCK:-}" ]] && env_args+=("SSH_AUTH_SOCK=${SSH_AUTH_SOCK}")
- [[ -n "${SSH_AGENT_PID:-}" ]] && env_args+=("SSH_AGENT_PID=${SSH_AGENT_PID}")
- [[ -n "${SSH_ASKPASS:-}" ]] && env_args+=("SSH_ASKPASS=${SSH_ASKPASS}")
- [[ -n "${GIT_ASKPASS:-}" ]] && env_args+=("GIT_ASKPASS=${GIT_ASKPASS}")
- [[ -n "${XDG_CONFIG_HOME:-}" ]] && env_args+=("XDG_CONFIG_HOME=${XDG_CONFIG_HOME}")
- [[ -n "${XDG_STATE_HOME:-}" ]] && env_args+=("XDG_STATE_HOME=${XDG_STATE_HOME}")
- [[ -n "${XDG_CACHE_HOME:-}" ]] && env_args+=("XDG_CACHE_HOME=${XDG_CACHE_HOME}")
- [[ -n "${XDG_DATA_HOME:-}" ]] && env_args+=("XDG_DATA_HOME=${XDG_DATA_HOME}")
- [[ -n "${XDG_RUNTIME_DIR:-}" ]] && env_args+=("XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR}")
- [[ -n "${GH_TOKEN:-}" ]] && env_args+=("GH_TOKEN=${GH_TOKEN}")
- [[ -n "${GITHUB_TOKEN:-}" ]] && env_args+=("GITHUB_TOKEN=${GITHUB_TOKEN}")
- [[ -n "${GH_HOST:-}" ]] && env_args+=("GH_HOST=${GH_HOST}")
- [[ -n "${GH_CONFIG_DIR:-}" ]] && env_args+=("GH_CONFIG_DIR=${GH_CONFIG_DIR}")
-
- run_clean_host_command_in_dir "${ROOT_DIR}" env \
- "${env_args[@]}" \
- "${HOST_GO_BIN}" run ./cmd/workcell-hostutil "$@"
-}
-
-go_colimautil() {
- ensure_go_run_env
- run_clean_host_command_in_dir "${ROOT_DIR}" env \
- GOPATH="${GOPATH}" \
- GOMODCACHE="${GOMODCACHE}" \
- GOCACHE="${GOCACHE}" \
- "${HOST_GO_BIN}" run ./cmd/workcell-colimautil "$@"
-}
+# Sourced after REAL_HOME and WORKCELL_GO_CACHE_ROOT are established so the
+# go_hostutil/go_colimautil wrappers this module defines can never be invoked
+# with an unsanitised host home or Go cache root (security ordering invariant;
+# see internal/testkit/security_boundary_test.go).
+# shellcheck source=/dev/null
+source "${ROOT_DIR}/scripts/lib/launcher/go-hostutil.sh"
HOST_GIT_BIN=""
HOST_COLIMA_BIN=""