diff --git a/deploy/README.md b/deploy/README.md index 4ae0861..af5728c 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -16,13 +16,20 @@ From a clone of this repository on the Mac mini: git fetch origin main git switch main git pull --ff-only -PYTHON_BIN="$(command -v python3)" PORT=4174 bash deploy/install_macos.sh +PORT=4174 bash deploy/install_macos.sh curl -fsS http://127.0.0.1:4174/api/health ``` The installer creates `~/Library/LaunchAgents/dev.oosu.elevator-queue-lab.plist`, keeps the process alive, and writes logs to `~/Library/Logs/elevator-queue-lab/`. +M8 requires **Python 3.11 or newer**. The installer prefers a supported Homebrew Python at +`/opt/homebrew/bin/python3` or `/usr/local/bin/python3`, then checks the `python3` available on +`PATH`. This matters on macOS because non-interactive SSH sessions can resolve `/usr/bin/python3` +to the Command Line Tools Python 3.9 even when a newer Homebrew Python is installed. To pin a +specific interpreter, pass `PYTHON_BIN=/absolute/path/to/python3`; unsupported versions fail before +launchd is modified. + ## 2. Publish `elevator.oosu.dev` Create a new DNS/tunnel hostname for `elevator.oosu.dev` in the same Cloudflare zone used by diff --git a/deploy/install_macos.sh b/deploy/install_macos.sh index b0851f6..576b29f 100644 --- a/deploy/install_macos.sh +++ b/deploy/install_macos.sh @@ -2,13 +2,51 @@ set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" -PYTHON_BIN="${PYTHON_BIN:-$(command -v python3)}" PORT="${PORT:-4174}" LABEL="dev.oosu.elevator-queue-lab" PLIST="$HOME/Library/LaunchAgents/$LABEL.plist" LOG_DIR="$HOME/Library/Logs/elevator-queue-lab" DOMAIN="${LAUNCHD_DOMAIN:-gui/$(id -u)}" +python_is_supported() { + local candidate="$1" + [ -x "$candidate" ] || return 1 + "$candidate" - <<'PY' >/dev/null 2>&1 +import sys + +raise SystemExit(0 if sys.version_info >= (3, 11) else 1) +PY +} + +select_python() { + local candidate + local path_python="" + + if [ -n "${PYTHON_BIN:-}" ]; then + if python_is_supported "$PYTHON_BIN"; then + printf '%s\n' "$PYTHON_BIN" + return 0 + fi + echo "PYTHON_BIN must point to Python 3.11 or newer: $PYTHON_BIN" >&2 + return 1 + fi + + path_python="$(command -v python3 2>/dev/null || true)" + for candidate in /opt/homebrew/bin/python3 /usr/local/bin/python3 "$path_python"; do + [ -n "$candidate" ] || continue + if python_is_supported "$candidate"; then + printf '%s\n' "$candidate" + return 0 + fi + done + + echo "Elevator Queue Lab requires Python 3.11 or newer." >&2 + echo "Install a supported Python or set PYTHON_BIN explicitly." >&2 + return 1 +} + +PYTHON_BIN="$(select_python)" + mkdir -p "$(dirname "$PLIST")" "$LOG_DIR" xml_escape() { diff --git a/docs/M8_PRODUCT_WORKBENCH.md b/docs/M8_PRODUCT_WORKBENCH.md index 296bc48..5897ade 100644 --- a/docs/M8_PRODUCT_WORKBENCH.md +++ b/docs/M8_PRODUCT_WORKBENCH.md @@ -333,6 +333,10 @@ The production contract remains: python3 -m app.server --port 4173 ``` +The runtime requires Python 3.11 or newer. The macOS launchd installer validates that requirement +and prefers a supported Homebrew Python before the system `python3`, because an SSH session on the +deployment Mac can otherwise resolve the older Command Line Tools Python first. + The server continues to serve `web/` and the API from one process. M8 therefore does not require a Node runtime on the deployed Mac mini once `web/` has been built and committed. The existing `deploy/` service/proxy structure can continue to target the same Python command and port.