From 6cfb527705833b5c9bcdb7f8e4ca15f1e862ffa8 Mon Sep 17 00:00:00 2001 From: Micah Alpern Date: Thu, 6 Aug 2026 16:39:52 -0700 Subject: [PATCH 1/2] Route desktop leases to the desktop base and fix silent create failures Two lab defects that compound: `create` failed with no diagnostic, and when it did succeed a --desktop lease landed on the wrong base. remote.sh runs over a non-interactive SSH shell, which does not source the login profile and so has no Homebrew on PATH. The repository sets core.hookspath, and those hooks call git-lfs. With git-lfs unreachable the hook exits non-zero and `set -e` aborts mid-command: `create` died right after staging its archive, reporting only exit 2 with nothing on stderr. The script now sets the PATH it needs instead of depending on how it was launched, which is the same convention the launcher branches already follow. base_for() ignored the desktop flag, so `--desktop` still resolved to the plain base. That base has no console session, no Homebrew, and no desktop tooling, so desktop-bootstrap failed and semantic UI automation could never run -- while the lease itself looked healthy. Thread desktop through to base_for and route macOS 26/27 desktop leases to keypath-macos-N-desktop. Managed lanes are excluded: only the managed base carries MDM enrollment, so a managed desktop lease keeps its base and takes desktop capability from the launcher. warmup_lease's remaining call sites are reached only when desktop is 0, so they keep the default. The existing desktop tests asserted the lease id but never the base, which is why this regressed invisibly. They now assert the recorded base_name for macOS 26 and 27, and that a managed desktop lease keeps the managed base. Reverting base_for makes the suite fail, confirming the tests bite. Verified against the real lab: create now runs through the controller with no PATH workaround and provisions `type=template-keypath-macos-27-desktop-base` with console user keypathqa, where it previously produced the plain base. Co-Authored-By: Claude Opus 5 --- Scripts/lab/remote.sh | 31 +++++++++++++++++++++----- Scripts/lab/tests/keypath-lab-tests.sh | 18 +++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/Scripts/lab/remote.sh b/Scripts/lab/remote.sh index 4877e1b1b..7169a0d5b 100755 --- a/Scripts/lab/remote.sh +++ b/Scripts/lab/remote.sh @@ -1,6 +1,18 @@ #!/bin/zsh set -euo pipefail +# This script runs over a non-interactive SSH shell, which does not source the +# login profile and therefore does not have Homebrew on PATH. That matters +# because the repository configures core.hookspath, and those hooks call +# git-lfs. A missing git-lfs makes the hook exit non-zero, and `set -e` then +# aborts mid-command with no diagnostic: `create` died after staging its +# archive, reporting only exit 2. Set the environment this script needs rather +# than depending on how it was launched. +for candidate in /opt/homebrew/bin /usr/local/bin; do + [[ -d "$candidate" && ":$PATH:" != *":$candidate:"* ]] && PATH="$candidate:$PATH" +done +export PATH + PRODUCTION_ROOT="/Volumes/KeyPath Lab/CrabBox" OWNER="keypath-installer-lab-v1" NAMEPLATE_VERSION="0.2.5" @@ -65,10 +77,19 @@ configure_tart_path() { export PATH="${usb_prefix}$LAB_ROOT/CompatTools/bin:$LAB_ROOT/SharedTools/bin:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin" } +# Desktop leases need the provisioned desktop base, which already carries the +# console session, Python, and the approved Peekaboo Lab Host. Without this the +# --desktop flag still produced a plain base, so desktop-bootstrap failed on a +# missing Homebrew and semantic UI automation could never run. Managed lanes are +# excluded: their base carries MDM enrollment that the desktop base does not, so +# a managed desktop lease keeps the managed base and gains desktop capability +# from the launcher instead. base_for() { - local macos=$1 lane=$2 + local macos=$1 lane=$2 desktop=${3:-0} if [[ "$macos" == "15" ]]; then [[ "$lane" == "managed-functional" ]] && print keypath-macos-15-managed || print ghcr.io/cirruslabs/macos-sequoia-base:latest + elif [[ ("$macos" == "26" || "$macos" == "27") && "$desktop" == "1" && "$lane" != "managed-functional" ]]; then + print "keypath-macos-$macos-desktop" else [[ "$lane" == "managed-functional" ]] && print "keypath-macos-$macos-managed" || print "keypath-macos-$macos" fi @@ -483,13 +504,13 @@ warmup_desktop() { if [[ "${USER:-}" == "clawd" ]]; then export TART_HOME="$LAB_ROOT/TartHome-clawd"; else export TART_HOME="$LAB_ROOT/TartHome"; fi configure_tart_path "$CRABBOX" warmup --provider tart --target macos --desktop \ - --tart-image "$(base_for "$macos" "$lane")" \ + --tart-image "$(base_for "$macos" "$lane" 1)" \ --tart-user admin --tart-cpu 4 --tart-memory 8192 --tart-random-serial --ssh-port 22 \ --slug "$slug" --ttl 2h else export PATH="$LAB_ROOT/SharedTools/bin:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin" "$CRABBOX" warmup --provider parallels --target macos --desktop \ - --parallels-template "$(base_for "$macos" "$lane")" --parallels-user keypathqa \ + --parallels-template "$(base_for "$macos" "$lane" 1)" --parallels-user keypathqa \ --parallels-work-root /Users/keypathqa/crabbox --ssh-port 22 \ --slug "$slug" --ttl 2h fi @@ -628,7 +649,7 @@ write_provisional_lease_manifest() { print "slug\t$slug" print "macos\t$macos" print "test_lane\t$lane" - print "base_name\t$(base_for "$macos" "$lane")" + print "base_name\t$(base_for "$macos" "$lane" "$desktop")" print "managed_identity_scope\t$identity_scope" print "provider\t$provider" print "archive_key\t$archive_key" @@ -731,7 +752,7 @@ create_lease() { print "slug\t$slug" print "macos\t$macos" print "test_lane\t$lane" - print "base_name\t$(base_for "$macos" "$lane")" + print "base_name\t$(base_for "$macos" "$lane" "$desktop")" print "managed_identity_scope\t$identity_scope" print "provider\t$provider" print "archive_key\t$archive_key" diff --git a/Scripts/lab/tests/keypath-lab-tests.sh b/Scripts/lab/tests/keypath-lab-tests.sh index 9c630a063..5a63501f7 100755 --- a/Scripts/lab/tests/keypath-lab-tests.sh +++ b/Scripts/lab/tests/keypath-lab-tests.sh @@ -426,6 +426,7 @@ managed_manifest="$ROOT/KeyPathInstallerLab/leases/cbx_test26/manifest.tsv" grep -q $'managed_policy_result\t0' "$managed_manifest" grep -q $'managed_identity_scope\tshared:26262626-2626-2626-2626-262626262626' "$managed_manifest" grep -q $'managed-policy-rehydration' "$ROOT/KeyPathInstallerLab/leases/cbx_test26/commands.tsv" +grep -q $'base_name\tkeypath-macos-26-managed' "$managed_manifest" set +e managed_busy_output=$(run_remote create 26 managed-functional "$archive_key" "$commit" "$checksum" KeyPath.zip 2h 0 2>&1) managed_busy_exit=$? @@ -565,6 +566,12 @@ grep -q 'stop-27 cbx_test27' "$CALLS" desktop27_create=$(run_remote create 27 unmanaged-ui "$archive_key" "$commit" "$checksum" KeyPath.zip 2h 1) assert_contains "$desktop27_create" $'lease_id\tcbx_desktop27' +# A desktop lease must land on the provisioned desktop base. Asserting only the +# lease id let the base silently regress to the plain template, which has no +# Homebrew, no console session, and no approved Peekaboo Lab Host. The recorded +# base_name is the assertable signal here: in test mode warmup_desktop calls the +# stub launcher without --parallels-template, so the calls log cannot show it. +grep -q $'base_name\tkeypath-macos-27-desktop' "$ROOT/KeyPathInstallerLab/leases/cbx_desktop27/manifest.tsv" test_known_hosts="$TMP/known hosts/known_hosts" mkdir -p "$(dirname "$test_known_hosts")" touch "$test_known_hosts" @@ -672,6 +679,7 @@ run_remote destroy cbx_desktop27 >/dev/null desktop26_create=$(run_remote create 26 unmanaged-ui "$archive_key" "$commit" "$checksum" KeyPath.zip 2h 1) assert_contains "$desktop26_create" $'lease_id\tcbx_desktop26' +grep -q $'base_name\tkeypath-macos-26-desktop' "$ROOT/KeyPathInstallerLab/leases/cbx_desktop26/manifest.tsv" rfb_probe26=$(KEYPATH_LAB_TEST_SSH_KEY="$TMP/test-ssh-key" KEYPATH_LAB_TEST_CURSOR_BEFORE='10 10' KEYPATH_LAB_TEST_CURSOR_AFTER='170 130' KEYPATH_LAB_RFB_POINTER_SETTLE_SECONDS=0 run_remote rfb-pointer-probe cbx_desktop26 170 130) assert_contains "$rfb_probe26" $'rfb_pointer_probe\tpassed' assert_contains "$rfb_probe26" $'cursor_before\t10 10' @@ -693,6 +701,16 @@ assert_contains "$invalid_resource_output" 'invalid Parallels resource id' [[ $(grep -c '^prlctl capture ' "$CALLS") -eq $prlctl_calls_before ]] run_remote destroy cbx_desktop26 >/dev/null +# A managed lease that also asks for a desktop must keep the managed base: only +# that base carries MDM enrollment. Desktop capability comes from the launcher, +# not from swapping to the unenrolled desktop base. +managed_desktop_create=$(run_remote create 26 managed-functional "$archive_key" "$commit" "$checksum" KeyPath.zip 2h 1) +assert_contains "$managed_desktop_create" $'lease_id\tcbx_desktop26' +managed_desktop_manifest="$ROOT/KeyPathInstallerLab/leases/cbx_desktop26/manifest.tsv" +grep -q $'base_name\tkeypath-macos-26-managed' "$managed_desktop_manifest" +grep -q $'desktop_enabled\ttrue' "$managed_desktop_manifest" +run_remote destroy cbx_desktop26 >/dev/null + desktop_create=$(run_remote create 15 unmanaged-ui "$archive_key" "$commit" "$checksum" KeyPath.zip 2h 1) assert_contains "$desktop_create" $'lease_id\tcbx_desktop15' grep -q $'status\tprovisioning' "$ROOT/KeyPathInstallerLab/leases/cbx_stale/manifest.tsv" From 51a5c86c99e9da42d314f47d29b46694393149db Mon Sep 17 00:00:00 2001 From: Micah Alpern Date: Fri, 7 Aug 2026 11:14:39 -0700 Subject: [PATCH 2/2] Measure the disk reserve on the volume clones actually use The provisioning guard called `df` on /System/Volumes/Data, the boot disk. Parallels writes clones to its configured VM folder, which on this host is an external volume, so the guard measured a filesystem the clone never touched. A full clone passed admission with 113 GiB free on the boot disk and then exhausted the external container it was really consuming. Make the measured path configurable via KEYPATH_LAB_DISK_RESERVE_PATH, defaulting to the previous location so behavior is unchanged until an operator points it at the real clone root. Emit that path in both the disk_reserve and disk_reserve_busy lines: a guard aimed at the wrong filesystem should be visible in the log instead of silently passing. Resolve df and awk absolutely. This guard runs before the environment is established and must not depend on PATH being well-formed. Co-Authored-By: Claude Opus 5 --- Scripts/lab/remote.sh | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/Scripts/lab/remote.sh b/Scripts/lab/remote.sh index 7169a0d5b..49377d82d 100755 --- a/Scripts/lab/remote.sh +++ b/Scripts/lab/remote.sh @@ -9,7 +9,9 @@ set -euo pipefail # archive, reporting only exit 2. Set the environment this script needs rather # than depending on how it was launched. for candidate in /opt/homebrew/bin /usr/local/bin; do - [[ -d "$candidate" && ":$PATH:" != *":$candidate:"* ]] && PATH="$candidate:$PATH" + if [[ -d "$candidate" && ":$PATH:" != *":$candidate:"* ]]; then + PATH="$candidate:$PATH" + fi done export PATH @@ -144,23 +146,36 @@ provider_capacity() { esac } +# The path whose free space gates provisioning. This must be the filesystem the +# provider actually writes clones to, which is not necessarily the boot disk: +# Parallels stores clones under its configured VM folder, which on this host is +# an external volume. Measuring the boot disk while clones land elsewhere let a +# full clone pass admission and then exhaust the volume it was really using. +disk_reserve_path() { + print -r -- "${KEYPATH_LAB_DISK_RESERVE_PATH:-/System/Volumes/Data}" +} + host_free_kib() { if [[ -n "${KEYPATH_LAB_TEST_FREE_KIB:-}" ]]; then print -r -- "$KEYPATH_LAB_TEST_FREE_KIB" else - df -Pk /System/Volumes/Data | awk 'NR == 2 {print $4}' + # Absolute paths: this guard must not depend on PATH being well-formed. + /bin/df -Pk "$(disk_reserve_path)" | /usr/bin/awk 'NR == 2 {print $4}' fi } assert_internal_disk_reserve() { - local minimum_gib=${KEYPATH_LAB_MIN_FREE_DISK_GIB:-100} free_kib minimum_kib + local minimum_gib=${KEYPATH_LAB_MIN_FREE_DISK_GIB:-100} free_kib minimum_kib path [[ "$minimum_gib" == <-> && "$minimum_gib" -gt 0 ]] || die "invalid disk reserve: $minimum_gib GiB" + path=$(disk_reserve_path) free_kib=$(host_free_kib) - [[ "$free_kib" == <-> ]] || die "could not determine internal free space" + [[ "$free_kib" == <-> ]] || die "could not determine free space for $path" minimum_kib=$((minimum_gib * 1024 * 1024)) - print -u2 "disk_reserve\tfree_gib=$((free_kib / 1024 / 1024))\tminimum_gib=$minimum_gib" + # Report the measured path so a guard pointed at the wrong filesystem is + # visible in the log rather than silently passing. + print -u2 "disk_reserve\tfree_gib=$((free_kib / 1024 / 1024))\tminimum_gib=$minimum_gib\tpath=$path" if (( free_kib < minimum_kib )); then - print -u2 "disk_reserve_busy\tfree_gib=$((free_kib / 1024 / 1024))\tminimum_gib=$minimum_gib" + print -u2 "disk_reserve_busy\tfree_gib=$((free_kib / 1024 / 1024))\tminimum_gib=$minimum_gib\tpath=$path" return 75 fi }