From cf081727f15cfeaadf3a21fbf1ef35212eab8305 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 21 Oct 2026 22:39:37 -0700 Subject: [PATCH 1/2] chore(quest): claim quest/m0/helpers/ci-guard.md Quest-Claim: f25310d9ae66b2b8 From b6aaa21c3bc3f48547b977362c25fc31f2a8a88d Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Wed, 21 Oct 2026 22:54:28 -0700 Subject: [PATCH 2/2] ci: run the landed-quest guard on pull requests The check job builds quest from the PR's base with Nix, before any of the head's code runs, and fails when a quest branch neither deletes nor rewrites its quest. Merges that skip /quest-merge are checked too, and the guard rides the already-required check status. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/check.yml | 28 +++++++++++++++++++++++++--- quest/m0/helpers/README.md | 1 - quest/m0/helpers/ci-guard.md | 19 ------------------- 3 files changed, 25 insertions(+), 23 deletions(-) delete mode 100644 quest/m0/helpers/ci-guard.md diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index cd7e83bc..b42cf1ce 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -21,12 +21,34 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - uses: DeterminateSystems/nix-installer-action@1d87d45818068401a10cf16bdc5f00b24994a83f with: determinate: false + # A PR from a quest's branch must delete or rewrite its quest. A quest + # built from the base checks that before any of the head's code runs on + # this runner, so the head cannot weaken the check it is held to. + - name: Check out the base + if: github.event_name == 'pull_request' + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.event.pull_request.base.sha }} + persist-credentials: false + - name: Build quest from the base + if: github.event_name == 'pull_request' + run: nix build --out-link "$RUNNER_TEMP/quest-base" .#quest + # The full history holds the merge base with the base branch. + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + persist-credentials: false + # The checkout is detached, so name the head branch. + - name: Check that the PR leaves its quest accurate + if: github.event_name == 'pull_request' + working-directory: ${{ runner.temp }} + env: + BASE_REF: ${{ github.base_ref }} + HEAD_REF: ${{ github.head_ref }} + run: ./quest-base/bin/quest --root "$GITHUB_WORKSPACE" check --base "origin/$BASE_REF" --branch "$HEAD_REF" - name: Install dependencies run: nix develop --command just install # `quest worktree run` owns processes through a systemd user scope, which the tests exercise. diff --git a/quest/m0/helpers/README.md b/quest/m0/helpers/README.md index 71061094..9e67b9de 100644 --- a/quest/m0/helpers/README.md +++ b/quest/m0/helpers/README.md @@ -65,7 +65,6 @@ commands from Sep-Oct. Session counts in each child come from that window. - [Headless agents](/quest/m0/helpers/headless-agents.md) - `/quest-spawn api` launches, resumes, and stops billed agents through one command auto mode allows - [Upstream claims](/quest/m0/helpers/claims.md) - claims and readiness read from the upstream tree, ignoring merged branches - [Wait gaps](/quest/m0/helpers/wait-gaps.md) - `quest wait` reports every event after its starting point exactly once -- [Guard in CI](/quest/m0/helpers/ci-guard.md) - pull request CI runs the landed-quest guard ## Related diff --git a/quest/m0/helpers/ci-guard.md b/quest/m0/helpers/ci-guard.md deleted file mode 100644 index 69c7ca38..00000000 --- a/quest/m0/helpers/ci-guard.md +++ /dev/null @@ -1,19 +0,0 @@ -# [XS] Run the landed-quest guard in CI - -## Goal - -This repository's pull request CI fails when a PR would leave its quest -inaccurate, so merges that skip `/quest-merge` are checked too. - -## Plan - -Decided 2026-10-21 as a follow-up of -[kixelated/quest#169](https://github.com/kixelated/quest/pull/169): - -- Run `quest check --base origin/ --branch ` (README, "Check a - quest's PR") in `.github/workflows/check.yml` on pull requests, using a - trusted `quest` built from the base branch, never the head's code or - runtime config, as the merge skill requires. -- Non-quest branches already pass, so no extra filtering is needed. -- Confirm it passes on a planning PR and fails on a PR that finishes a quest - without deleting or updating it.