From aca23fd1257194165ac2dfe876ec5bfcf75ad63e Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Tue, 25 Aug 2026 14:45:29 +0000 Subject: [PATCH 1/4] ci: make GitHub release job self-contained --- .github/workflows/release.yml | 22 +++++++++++++++++++++- tests/test_deploy.py | 2 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 15531ff..5724c45 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -652,6 +652,26 @@ jobs: jq empty release-assets/final/vogt-release-manifest.json jq -r . release-assets/final/vogt-release-manifest.json > release-assets/release-notes.json + - name: install GitHub CLI + run: | + set -euo pipefail + command -v gh >/dev/null 2>&1 && exit 0 + if command -v apt-get >/dev/null 2>&1; then + if [ "$(id -u)" -eq 0 ]; then + apt-get update + apt-get install -y --no-install-recommends gh + else + sudo apt-get update + sudo apt-get install -y --no-install-recommends gh + fi + elif command -v apk >/dev/null 2>&1; then + apk add --no-cache github-cli + else + echo "GitHub CLI is required on the release runner" >&2 + exit 1 + fi + command -v gh >/dev/null 2>&1 + - name: create or update the GitHub Release env: GH_TOKEN: ${{ github.token }} @@ -662,7 +682,7 @@ jobs: notes="$(mktemp)" trap 'rm -f "$notes"' EXIT { - echo "Release metadata (machine-readable copy is attached as \\`vogt-release-manifest.json\\`):" + echo 'Release metadata (machine-readable copy is attached as `vogt-release-manifest.json`):' echo echo '```json' cat release-assets/release-notes.json diff --git a/tests/test_deploy.py b/tests/test_deploy.py index a5459ee..6a3f95c 100644 --- a/tests/test_deploy.py +++ b/tests/test_deploy.py @@ -1255,6 +1255,8 @@ def test_github_release_collects_and_publishes_the_complete_release() -> None: assert "CORE_DIGEST" in job and "STACK_DIGEST" in job assert "vogt-release-manifest.json" in job assert "production_deployment_handoff" in job + assert "name: install GitHub CLI" in job + assert "command -v gh" in job assert "gh release upload" in job assert "--clobber" in job From da889970fb95074b5110270017a54dd9a6777148 Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:45:10 +0000 Subject: [PATCH 2/4] ci: authenticate dev deployment image pull --- .github/workflows/deploy-dev.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 7f6ab79..152e9b5 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -45,6 +45,13 @@ jobs: - uses: sigstore/cosign-installer@v3 + - name: authenticate to the dev registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: resolve and verify the signed dev image id: image env: From 14f970a882189cb810dc5f414924cdc133c5a07b Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Tue, 25 Aug 2026 16:23:27 +0000 Subject: [PATCH 3/4] ci: avoid duplicate merged-image cache export --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c5e82dc..7c09bda 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -690,7 +690,6 @@ jobs: # Same cache ref as the candidate: every layer is a hit, so the push # is a re-tag of the smoke-tested bytes rather than a recompile. cache-from: type=registry,ref=${{ env.CACHE_IMAGE }}:stack-${{ github.ref_name }} - cache-to: type=registry,ref=${{ env.CACHE_IMAGE }}:stack-${{ github.ref_name }},mode=max - uses: sigstore/cosign-installer@v3 From b4a46525f016d61577dc12bcd3a81d496d794f42 Mon Sep 17 00:00:00 2001 From: thedancingdeveloper <306930456+thedancingdeveloper@users.noreply.github.com> Date: Wed, 26 Aug 2026 00:26:38 +0000 Subject: [PATCH 4/4] fix(engine): drain PTY output before concluding runs --- engine/server/src/pty.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/engine/server/src/pty.rs b/engine/server/src/pty.rs index 915537b..7c8908e 100644 --- a/engine/server/src/pty.rs +++ b/engine/server/src/pty.rs @@ -440,6 +440,15 @@ fn spawn_exit_waiter( let new_state = compute_activity(&session, code != 0); update_activity_if_changed(&session, new_state, &bus); wake_activity_watcher(&session); + + // The child can exit before the PTY reader has consumed the final + // bytes. Publish the terminal event only after that reader has + // drained its stream; agent-task conclusions inspect scrollback when + // they receive `SessionKilled` (including VOGT_SKIP and VOGT_COST + // sentinels printed immediately before exit). + while !session.reader_done.load(Ordering::Acquire) { + std::thread::sleep(std::time::Duration::from_millis(1)); + } bus.publish(ServerEvent::SessionKilled { id: session.id, exit_code: Some(code),