From ad36cb7205bcb1783c2cb0101f7e46048c203340 Mon Sep 17 00:00:00 2001 From: Kyle Sexton <153232337+kyle-sexton@users.noreply.github.com> Date: Wed, 11 Nov 2026 09:44:25 -0500 Subject: [PATCH 1/9] feat(pr-pipeline): stop lanes at their start gate on a low GITHUB_TOKEN budget check-kill-switch now gates on the GITHUB_TOKEN budget as well as the two manual switches. With both switches off it makes one GET /rate_limit with the job's token, reads the core pool from the x-ratelimit-* headers (else the body's resources.core), and stops the lane while remaining is under limits.api github-token start-gate (default 0.1) of the limit and the reset is ahead. A failed read proceeds with a warning. Each switch also accepts true@, which stops until that time. Every stop keeps reason=kill-switch; a new cause output names switch, expiry, budget or ok. The read runner marks a budget stop with a top-level step, so work-unblock's sweep tells it apart from the job listing alone: it re-fires such a run on the next sweep, and its record never counts toward limits.limit-stops-per-issue or the flat kill-switch wait. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VQb9Q1HHi6JACp77x2ZbE7 --- ...-kill-switch-start-gate-budget-16d00f6e.md | 7 + .github/actions/check-kill-switch/README.md | 37 ++- .github/actions/check-kill-switch/action.yml | 30 ++- .../check-kill-switch/check-kill-switch.mjs | 135 +++++++++- .../check-kill-switch.test.mjs | 251 +++++++++++++++++- .github/actions/log-api-budget/rate-guard.mjs | 7 +- .../actions/log-api-budget/rate-limits.json | 2 +- .../scripts/work-unblock/label-unblocked.mjs | 53 ++-- .../work-unblock/label-unblocked.test.mjs | 76 ++++++ .github/workflows/pr-run-activity-read.yml | 12 + docs/conventions/pr-pipeline.yaml | 4 +- docs/conventions/pr-pipeline/README.md | 2 +- .../pr-pipeline/pr-pipeline.schema.json | 6 + 13 files changed, 563 insertions(+), 59 deletions(-) create mode 100644 .changes/pr-pipeline/feat-kill-switch-start-gate-budget-16d00f6e.md diff --git a/.changes/pr-pipeline/feat-kill-switch-start-gate-budget-16d00f6e.md b/.changes/pr-pipeline/feat-kill-switch-start-gate-budget-16d00f6e.md new file mode 100644 index 00000000000..29cb22566c8 --- /dev/null +++ b/.changes/pr-pipeline/feat-kill-switch-start-gate-budget-16d00f6e.md @@ -0,0 +1,7 @@ +--- +bump: minor +--- + +### Added + +- `limits.api.github-token.start-gate`, a share of the header's `x-ratelimit-limit` (default 0.1, in `.github/actions/log-api-budget/rate-limits.json`). The kill-switch gate (`.github/actions/check-kill-switch`) now also stops a lane at its start while the GITHUB_TOKEN core pool's remaining is under that share and the reset is still ahead, from one GET /rate_limit with the job's token (its `x-ratelimit-*` headers, else the body's `resources.core`). The stop keeps `reason=kill-switch`; a new `cause` output says `switch`, `expiry`, `budget` or `ok`. A failed or unreadable read proceeds with a warning. Each switch variable also accepts `true@`, which stops until that time. work-unblock's sweep re-fires a budget-stopped issue run on its next sweep and never counts it toward `limits.limit-stops-per-issue`. diff --git a/.github/actions/check-kill-switch/README.md b/.github/actions/check-kill-switch/README.md index b1d5a59d9fb..d33c3309010 100644 --- a/.github/actions/check-kill-switch/README.md +++ b/.github/actions/check-kill-switch/README.md @@ -1,10 +1,33 @@ # check-kill-switch -Gate a CI lane on the org and repository kill switches before its model step. The lane proceeds -only when both read exactly `false`; a switch that is unset, empty or holds any other value stops -it +Gate a CI lane on the org and repository kill switches, then on the GITHUB_TOKEN budget, before +its model step. Each switch proceeds only on exactly `false`, or on `true@