From 3100e90453762091999a0a410746fd06ec51c381 Mon Sep 17 00:00:00 2001 From: danielhanchen Date: Tue, 28 Jul 2026 15:14:06 +0000 Subject: [PATCH] Fail the leg when the installer finished instead of being killed The driver set reason=marker-hit before the post-marker sleep and never rechecked, so a step whose work was already cached could run to completion inside that beat and still be recorded as an interruption. The landing assertion tests reason != marker-hit, so a fully completed install passed green having interrupted nothing. Reproduced with a stub that exits during the delay: reported marker-hit / killed=true / exit=0 next to "install finished fully". Set the reason after the sleep, on both drivers. Also trigger on _studio_deps.py and install_manifest.py, where the two decisions the probe asserts on are actually implemented. --- .github/scripts/interrupt-install.ps1 | 5 ++++- .github/scripts/interrupt-install.sh | 10 +++++++++- .github/workflows/interrupted-install-ci.yml | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.github/scripts/interrupt-install.ps1 b/.github/scripts/interrupt-install.ps1 index 038c6a794a..0cdafed048 100644 --- a/.github/scripts/interrupt-install.ps1 +++ b/.github/scripts/interrupt-install.ps1 @@ -65,8 +65,11 @@ for ($i = 0; $i -lt $KillAtSeconds; $i++) { if ($Marker) { $hit = Select-String -Path $LogPath -Pattern $Marker -SimpleMatch:$false -ErrorAction SilentlyContinue if ($hit) { - $reason = 'marker-hit' Start-Sleep -Seconds $KillAfterMarkerSeconds + # The installer can finish inside the delay; recording marker-hit before it + # let a COMPLETED install satisfy the landing assertion and probe HEALTHY. + if ($proc.HasExited) { $reason = 'exited-during-marker-delay'; break } + $reason = 'marker-hit' $killed = $true break } diff --git a/.github/scripts/interrupt-install.sh b/.github/scripts/interrupt-install.sh index 9f3fa3a49d..e805b11d90 100755 --- a/.github/scripts/interrupt-install.sh +++ b/.github/scripts/interrupt-install.sh @@ -56,10 +56,18 @@ for i in $(seq 1 "$KILL_AT_SECONDS"); do break fi if [ -n "$MARKER" ] && grep -qE "$MARKER" "$LOG" 2>/dev/null; then - reason="marker-hit" # Let it get a beat into the step, so the kill lands mid-work rather than on the # boundary where the step has not started touching the venv yet. sleep "${KILL_AFTER_MARKER_SECONDS:-3}" + # ...but a late step whose work is already cached can FINISH inside that beat. + # Recording marker-hit before the sleep handed the landing assertion a COMPLETED + # install: the signal reached no process, the probe read HEALTHY, and the leg + # passed green having interrupted nothing. Set the reason after, not before. + if ! kill -0 "$PID" 2>/dev/null; then + reason="exited-during-marker-delay" + break + fi + reason="marker-hit" killed=true break fi diff --git a/.github/workflows/interrupted-install-ci.yml b/.github/workflows/interrupted-install-ci.yml index 7f09174e17..319cf4ba4e 100644 --- a/.github/workflows/interrupted-install-ci.yml +++ b/.github/workflows/interrupted-install-ci.yml @@ -31,6 +31,12 @@ on: - 'studio/src-tauri/src/preflight.rs' - 'studio/src-tauri/src/preflight/**' - 'unsloth_cli/commands/studio.py' + # studio_install_ok and verify-install, the two decisions the probe asserts + # on, are implemented here rather than in commands/studio.py, so a change + # that made install_state() accept a missing manifest would otherwise merge + # without a single leg running. + - 'unsloth_cli/_studio_deps.py' + - 'studio/install_manifest.py' # `*` never matches `/`, and it is a literal `-install` that follows, so # `interrupt*-install*` matches interrupt-install.sh / .ps1 but NOT the # underscored probe. List the probe explicitly rather than rely on a glob.