Absorbs #4412 (tomas-forgac) rebased onto fresh master, plus two
Codex-regression-gate fixes: (1) use the scheme that actually answered the
probe for the ready/already-up URL + browser-open, (2) honor an explicit
HERMES_WEBUI_HEALTH_URL override in the WSL autostart probe.
Co-authored-by: tomas-forgac <tomas-forgac@users.noreply.github.com>
Closes#4412
Codex regression gate found the launchd guard blocked ANY ctl.sh start while a
launchd job was live — including a legitimate second instance on a different
port (HERMES_WEBUI_PORT=8788). Now _launchd_webui_pid only treats the launchd
job as a conflict when its PID is actually listening on the requested CTL_PORT
(via a new best-effort _pid_listens_on_port helper using lsof); a different-port
start is allowed. When port ownership can't be determined (no lsof), falls back
to guarding only the default 8787 port so non-default ports are never wrongly
blocked. Adds a different-port-allowed regression test + makes the existing
block test deterministic. Co-authored-by preserved.
The _load_repo_dotenv_preserving_env() function iterates over
${preserved[@]} with set -euo pipefail. On bash 3.2 (macOS default),
an empty array triggers 'unbound variable' under set -u, crashing
ctl.sh start. Bash 4+ handles this fine, but macOS ships 3.2.
Wraps the for loop in a length check: [[ ${#preserved[@]} -gt 0 ]]
With set -u, bash 3.2 treats empty array expansion
"\${CTL_BOOTSTRAP_ARGS[@]}" as an unbound variable.
Use ${CTL_BOOTSTRAP_ARGS[@]+"..."} pattern to skip
expansion when the array is empty.
Replace [[ -v ${key} ]] (requires bash 4.2+) with
[[ -n "${!key+x}" ]] which works on bash 3.2+ and all
POSIX-compatible shells.
macOS ships with bash 3.2, causing:
./ctl.sh: line 42: conditional binary operator expected