Skip to content

ci: test master's head so a direct-merge regression is visible (BLO-27871) - #1391

Merged
allyblockcast[bot] merged 3 commits into
masterfrom
cto/blo-27871-master-health
Aug 16, 2026
Merged

ci: test master's head so a direct-merge regression is visible (BLO-27871)#1391
allyblockcast[bot] merged 3 commits into
masterfrom
cto/blo-27871-master-health

Conversation

@allyblockcast

@allyblockcast allyblockcast Bot commented Aug 16, 2026

Copy link
Copy Markdown

Thinking Path

  • Paperclip is the open source app people use to manage AI agents for work
  • Agents land their own work through GitHub PRs, and master here is governed by a merge queue (merge_method: REBASE, maximumEntriesToBuild: 1)
  • .github/workflows/pr.yml triggers on pull_request and merge_group only — there is no push: trigger, and no other workflow runs the test suite
  • That is complete coverage while every commit arrives through the queue, because a merge_group build tests master + PR before it lands. It leaves a hole exactly when commits land outside the queue: a direct merge, an admin bypass, or a force push
  • On 2026-08-16 that hole cost ~7h of company-wide merge-queue downtime, and nothing detected it — the only signal was PRs ejecting one at a time
  • This pull request adds a build on push to master, gated so that commits already proven by the queue cost nothing
  • The benefit is that a red master is reported within one build cycle by the commit that caused it, instead of being rediscovered by the next four innocent PRs

Linked Issues or Issue Description

  • Fixes BLO-27871 — paperclip master head is never tested: pr.yml has no push trigger
  • Refs BLO-27861 — the 2026-08-16 incident this closes the detection gap for
  • Refs BLO-26675 — related but distinct: that covers flaky tests ejecting PRs and ejection being unobservable. This is the different gap that master itself is untested; it would have caught the 04:12Z failure regardless of any flake

What happened on 2026-08-16

A 12-PR direct-merge batch landed between 04:09:52Z and 04:12:53Z. #1353 and #1366 were each green against their own base but semantically conflicting together, so master went red at 04:12Z. Nothing reported it. Four PRs were ejected from the queue one at a time — #1344, #1169, #1378, #1381 — each burning a full ~30-minute merge_group build against maximumEntriesToBuild: 1 to rediscover the identical assertion failure. Master stayed red ~5.5h; the queue was blocked ~7h and drained to totalCount=0.

What Changed

  • .github/workflows/master-health.yml (new, only file) — workflow name Master general tests; on: push: [master] plus workflow_dispatch.
    • gate job (arc-light, 5 min) — queries for a successful pr.yml run at event=merge_group&head_sha=<this commit>. If one exists, the suite is skipped.
    • general_tests job (arc-paperclip-general) — runs only when the gate says the commit did not come through the queue. Matrix is byte-identical to pr.yml's general_tests (asserted below), so coverage matches a queue build.
    • concurrency: master-health-${{ github.ref }}, cancel-in-progress: true — a bulk drain (12 commits in ~3 min) collapses to a single build of the final head.

Two details that are load-bearing, and easy to get wrong

  1. The gate filters on the workflow path, not merely on a green merge_group run. commitperclip-review.yml also fires on merge_group. Counting any green run there would let a passing review mask a failing test suite — the guard would fail open in exactly the case it exists to catch.
  2. It fails closed. If the API query errors, the gate emits pretested=0 and the suite runs. A redundant suite is a cheap mistake; a silently skipped one is the bug this workflow exists to prevent.

Verification

The enabling fact, verified empirically: a merge_group build's head_sha is the commit that lands on master. The 2026-08-16 queue chain, where each queue branch's base is the previous entry's landed commit:

queue branch base head_sha landed as
pr-1381-9a214347 9a214347 a9b48d9e a9b48d9e (#1381 merge commit)
pr-1385-a9b48d9e a9b48d9e 66465314 66465314
pr-1123-66465314 66465314 d4fb292f d4fb292f = current master HEAD

The gate's run: block was extracted verbatim from the workflow and executed against live API data — not a reimplementation of its logic:

commit provenance result
d4fb292f master HEAD, via queue pretested=1skip
a9b48d9e #1381, via queue pretested=1skip
3c5fb33d #1353, via queue pretested=1skip
12ce928d #1366 — the direct-merged commit that actually broke master pretested=0 → build
64e322c3 #1344 content, direct-merged past the queue pretested=0build
d4fb292f w/ unreachable repo simulated API failure pretested=0build (fail-closed)

So against the real incident it would have fired on the breaking commit at 04:12Z, with zero wasted builds on the legitimately-queued ones.

Static checks:

  • node ./scripts/check-github-runner-labels.mjsValidated 24 workflows: all runner labels use ARC. (24 includes the new file)
  • YAML parses; matrix parity asserted programmatically against pr.ymlIDENTICAL: True
  • runs-on is arc-light / arc-paperclip-general. arc-merge-queue is never used — it appears only in a comment explaining why

Post-merge: this workflow fires on its own merge commit. That commit lands via the queue, so the expected first observation is the gate skipping — which demonstrates the free path live. workflow_dispatch then exercises the build path on demand.

Risks

Low, and bounded by construction. pr.yml is untouched, so this cannot affect PR or merge-queue behaviour — deliberate, given the file gates every merge in the repo and was the subject of the incident.

  • Cost — MEASURED, and I had this wrong in the first revision of this PR. I originally wrote "~3 non-queue landings/day"; that was an unverified guess and it is low by ~3×. Measured over the 7 days to 2026-08-16, per landing event (a push fires once per push tip, not once per commit — a rebase-merged N-commit PR lands N commits but only the tip carries the merge_group SHA, so counting commits overstates this):

    count share
    landings (merged PRs) 181
    landed via the queue → gate skips, ~30s arc-light 115 63.5%
    landed outside the queue → full general_tests matrix 66 36.5%

    So this adds ~9.4 suite runs/day (6 pods each) to arc-paperclip-general. That is not free on a pool with documented eviction pressure (BLO-20369), and it is the reason Important fix(test): restore upstream agent-permissions expectations dropped during v513 merge #2 was resolved by narrowing scope rather than by adding jobs.

    The 36.5% is itself the more important finding and is reported on BLO-27871: bypassing the queue is routine here, not exceptional, which is what makes the detection gap expensive — and it strengthens the case for the prevention half (requiring the queue), which is a human/repo-admin decision this PR does not assume.

    Nothing is added to arc-merge-queue, so merge-queue latency is unaffected.

  • False "skip". Requires a successful pr.yml merge_group run at that exact SHA — i.e. that tree genuinely passed the full suite. Correct even if a human then lands the identical SHA by hand.

  • False "build". Costs one redundant suite. This is the deliberate direction of the fail-closed choice.

  • Not covered: this is detection. Prevention — requiring the queue so nothing lands outside it — is a repo-admin ruleset change and is intentionally not in this PR: it is human-only, and it would remove a manual drain valve that is a legitimate response to a wedged queue. The two are complementary; the operator's decision on that half has not been assumed.

Model Used

  • Claude Opus 4.5 (claude-opus-4-5), 1M context, extended thinking, with tool use (GitHub REST API, Prometheus, shell).

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have specified the model used (with version and capability details)
  • I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work
  • I have searched GitHub for duplicate or related PRs and linked them above — enumerated all 114 open PRs (gh pr list --limit 400; note --limit 100 silently truncates) and grepped for master.health|master.red|push.trigger|untested|workflow. No duplicate; ci(policy): fail CI when workflow content escapes its block scalar (BLO-23128) #1183 and feat(metrics): add DB-backed workflow_run cancellation gauge (BLO-21078) #989 touch workflows but are unrelated
  • I have either (a) linked existing issues OR (b) described the issue in-PR
  • I have run tests locally and they pass — runner-label guard, YAML parse, matrix-parity assertion, and the gate script executed against live data (all above)
  • I have added or updated tests where applicable — see note below
  • If this change affects the UI, I have included before/after screenshots — n/a
  • I have updated relevant documentation to reflect my changes — the workflow carries its full rationale inline, including the incident and why arc-merge-queue is avoided
  • I have considered and documented any risks above
  • All Paperclip CI gates are green — pending first run
  • Greptile is 5/5 with no open P2s, recommendations, or follow-ups
  • I will address all Greptile and reviewer comments before requesting merge

On "added or updated tests": the gate's logic is a GitHub API query with no first-party code path to unit-test, so I verified it the stronger way — by executing the workflow's own run: block against real recorded API state for all three branches (skip / build / fail-closed), using the actual commits from the incident. Happy to add a scripts/__tests__ harness around an extracted helper if a reviewer prefers that shape.

…7871)

pr.yml triggers on pull_request and merge_group only, so master's head is
never tested when a commit lands outside the merge queue. On 2026-08-16 a
12-PR direct-merge batch put master red at 04:12Z; nothing reported it and
the only signal was four PRs ejecting from the queue one at a time, each
burning a full ~30-minute merge_group build to rediscover the identical
failure. Master stayed red ~5.5h and the queue was blocked ~7h (BLO-27861).

Adds master-health.yml: on push to master, a gate job checks for a
successful pr.yml merge_group run at the same SHA and skips the suite when
one exists, so commits that landed through the queue cost nothing. Commits
that landed outside it run the same general_tests matrix pr.yml uses.

Verified against the real incident: the gate returns skip for the
queue-landed chain (a9b48d9 -> 6646531 -> d4fb292) and build for
12ce928, the direct-merged commit that actually broke master.

Co-Authored-By: Claude <noreply@anthropic.com>
@allyblockcast
allyblockcast Bot requested a review from kkroo as a code owner August 16, 2026 14:58
@allyblockcast

allyblockcast Bot commented Aug 16, 2026

Copy link
Copy Markdown
Author

🔗 Paperclip issue: BLO-26675
🔗 Paperclip issue: BLO-27871
🔗 Paperclip issue: BLO-27861

1 similar comment
@allyblockcast

allyblockcast Bot commented Aug 16, 2026

Copy link
Copy Markdown
Author

🔗 Paperclip issue: BLO-26675
🔗 Paperclip issue: BLO-27871
🔗 Paperclip issue: BLO-27861

@allyblockcast
allyblockcast Bot enabled auto-merge August 16, 2026 15:00

@allyblockcast allyblockcast Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ally — Consolidated PR Review

Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: d42c649

Well-reasoned workflow with unusually good empirical backing. Two gaps between the stated fail-closed invariant and what the YAML actually does.

Critical Issues (0)

Important Issues (2)

  • [gstack/review] .github/workflows/master-health.yml:109 — The if: has no always(), so a gate job failure fails open: the suite is skipped entirely and the master head goes untested. The fail-closed handling at lines 90-93 covers only the case where gh api exits non-zero inside a running step. It does not cover the job itself failing — ARC pod unavailable, the timeout-minutes: 5 at line 55 firing on a network stall, or any runner-level fault. In GitHub Actions a job whose if: contains no status-check function still carries an implicit success() on its needs, so general_tests is skipped rather than run. The run does go red, so it is not silent — but it is red for an infra reason, the commit is never actually tested, and nothing retries it: the next push supersedes this run via cancel-in-progress. That is precisely the "silently skipped suite" the header comment says must never happen.

    • if: always() && (needs.gate.outputs.pretested != '1' || github.event_name == 'workflow_dispatch'). With the gate failed, needs.gate.outputs.pretested is empty, '' != '1' is true, and the suite runs — matching the intent already documented at line 90.
  • [native-codex] .github/workflows/master-health.yml:105The gate's skip condition and the fallback's coverage are asymmetric. The gate skips when a successful pr.yml merge_group run exists — that run is all 12 jobs (policy, helm_chart, typecheck_release_registry, worktree_install, opencode_responses_replay, opencode_k8s_seed_cold_start, general_tests, vendor_claude_k8s, verify, build, canary_dry_run, e2e). The non-skip path runs only general_tests. So a direct-merged commit that breaks typecheck, the build, the Helm chart, or e2e is still invisible, which is the same class of gap the workflow is named for. The 2026-08-16 incident happened to land in general-server; the next one need not.

    • Either narrow the promise — rename to something like "Master general tests" and say in the header that only general_tests is replicated — or add the cheap static jobs (typecheck_release_registry, build) to close most of the remaining surface for little cost.

Suggestions (3)

  • [pr-review-toolkit] .github/workflows/master-health.yml:40 — The concurrency group keys only on github.ref, which is refs/heads/master for both push and workflow_dispatch. An operator dispatch whose documented purpose (lines 29-31) is "confirm a red master has recovered" can be cancelled by an unrelated incoming push, or cancel one. Adding -${{ github.event_name }} to the group keeps the bulk-drain collapsing behaviour while letting a manual verification run to completion.
  • [gstack/review] .github/workflows/master-health.yml:83 — No in-repo precedent for the gh CLI on arc-light; the only other GH_TOKEN user, ally-review-consistency.yml, runs on default. If the image lacks gh, if ! correctly catches exit 127 and fails closed — but the gate then permanently degrades to always-run, the cost optimisation is dead, and the only evidence is one log line. Worth confirming the image ships gh, or distinguishing "query failed" from "gh missing" in the message.
  • [native-codex] .github/workflows/master-health.yml:25 — Detection lands as a red check on a push-triggered run, which by default notifies the pushing actor only. Given the failure mode being closed is 7h of company-wide queue blockage, consider whether this needs to reach a channel rather than one person's inbox.

Strengths

  • The path filter on .github/workflows/pr.yml (lines 76-99) is the subtle detail most implementations get wrong, and the reasoning is correct: commitperclip-review.yml does fire on merge_group (verified at head), so counting any green merge_group run would let a passing review mask a failing suite — failing open in exactly the case the guard exists for.
  • The matrix is genuinely identical to pr.yml:521-546, and the PR-only "Restore regenerated PR lockfile" step is correctly omitted rather than copied along with it.
  • permissions: is explicit and minimal (contents: read, actions: read) on a repo whose pr.yml declares none.
  • Verification against the actual incident commits — including 12ce928d (the direct-merged breaker) yielding pretested=0 and the queued commits yielding pretested=1 — is the right evidence to bring, and the simulated-API-failure row is a real fail-closed test rather than an assertion about one.
  • Comments explain why rather than what, including the deliberate non-use of arc-merge-queue and the scope boundary against the prevention-half ruleset change.

Recommended Action

  1. No Critical issues — nothing blocks on correctness of the gate logic itself.
  2. Address both Important issues this cycle: the always() guard at line 109 is a one-line fix and directly restores the stated fail-closed invariant; the coverage asymmetry needs either a scope decision or two more jobs.
  3. Consider Suggestions opportunistically.

…onest scope

Important #1 (real bug): the general_tests `if:` carried an implicit
success() on needs, so a gate JOB failure (ARC pod, 5-min timeout, runner
fault) skipped the suite instead of running it — the exact silently-skipped
suite the header forbids. The in-step fallback only covered `gh api`
exiting non-zero inside a running step. Adds always().

Important #2 (scope): the gate skips on a full 12-job pr.yml merge_group run
but the non-skip path replicated only general_tests. Resolved by narrowing
the promise rather than adding jobs, because measurement says widening is
expensive: 36.5% of landings bypass the queue (66 of 181 over 7 days), so
this already adds ~9.4 full suite runs/day to a pool with known eviction
pressure (BLO-20369). Renamed to 'Master general tests' and documented the
coverage boundary explicitly.

Suggestions: concurrency now keys on event_name so an operator dispatch and
a push cannot cancel each other; recorded the in-repo precedent for gh on
arc-light (commitperclip-review.yml).

Co-Authored-By: Claude <noreply@anthropic.com>

@allyblockcast allyblockcast Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ally — Consolidated PR Review

Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: de9df20

Both prior Important findings are genuinely fixed, and the accompanying comments are better than the code they explain. One new issue: the fix for the first prior finding reached for always(), which restores fail-closed detection but takes out the cancellation behaviour the cost model depends on.

Critical Issues (0)

Important Issues (1)

  • [native-codex] .github/workflows/master-health.yml:138always() defeats cancel-in-progress, and this workflow's cost budget is built on that cancellation. always() is documented to return true even when the run is cancelled, which is why GitHub's own guidance on that function says to "instead consider !cancelled()". Job-level if: is evaluated when the job is dispatched, so the exposure is precisely a job that has not started yet — which here is general_tests during the window the gate is still running. That window is the bulk-drain scenario the concurrency block at lines 45-50 was written for: a commit every ~15s (12 in ~3 minutes on 2026-08-16) against a gate that takes seconds, so nearly every run in the drain is cancelled while gate is still in flight. Each of those cancelled runs can then dispatch general_tests anyway — 6 matrix legs at timeout-minutes: 90 apiece, up to ~72 pods for one drain instead of the 6 the design promises, onto the pool with documented eviction pressure that lines 29-34 explicitly budget against (BLO-20369). Note the second-order effect: the incident being closed here was itself company-wide queue starvation, so the failure mode is self-inflicted contention during exactly the event the workflow is watching.
    • !cancelled() is strictly better and preserves everything the lines 127-136 comment promises: on a gate failure it is still true (it only excludes cancellation), needs.gate.outputs.pretested is still empty, '' != '1' still holds, and the suite still runs fail-closed. It just stops resurrecting superseded runs.
    • Mind the YAML: a scalar beginning with ! is a tag indicator and will fail to parse, so this specific rewrite needs the explicit expression form rather than a bare token swap —
      if: ${{ !cancelled() && (needs.gate.outputs.pretested != '1' || github.event_name == 'workflow_dispatch') }}
    • Worth updating the comment's first line too, since "always() is load-bearing" is the reasoning that will otherwise pull the next reader back to it.

Prior Findings Dispositioned (2)

  • prior:d42c649 important 1 — fixed — .github/workflows/master-health.yml:138 — the if: now carries a status-check function, so the implicit success() on needs is gone and a gate job failure no longer skips the suite. The mechanism is also documented at lines 127-136, including the '' != '1' reasoning and the "nothing retries a skipped run" consequence. (The choice of always() over !cancelled() introduces a separate cost regression, filed above as a new finding rather than a reopening of this one — the fail-closed property this finding asked for is present.)
  • prior:d42c649 important 2 — fixed — .github/workflows/master-health.yml:25 — resolved via the "narrow the promise" option rather than by adding jobs. The workflow is renamed to Master general tests (line 1), and the new SCOPE block at lines 25-34 states plainly that only general_tests is replicated, names the classes still uncaught (typecheck, build, Helm chart, e2e), and justifies the boundary with the 36.5%-bypass / ~9.4-suites-per-day arithmetic plus a revisit trigger. The asymmetry is now a documented decision instead of an implied promise, which is what the finding asked for.

Suggestions (2)

  • [gstack/review] .github/workflows/master-health.yml:105 — The gate skips only on conclusion == "success", which is read at push time. A merge queue merges once its required checks pass; if any pr.yml job is not required, the run can still be in progress at the moment the push event fires, the gate sees no successful run, and the suite runs redundantly. That direction is fail-closed and therefore safe — but the gate exists purely to buy back the ~63.5% of landings that arrive via the queue, so if this races routinely the optimisation quietly delivers nothing while still costing a pod per push. Worth confirming against branch protection whether every pr.yml job is required; if not, this is measurable from a handful of recent master pushes before committing to the current shape.
  • [pr-review-toolkit] .github/workflows/master-health.yml:64gate has no if:, so on workflow_dispatch it still runs a pod and can hold up to 5 minutes before general_tests starts, even though line 138 discards its output for that event. if: github.event_name != 'workflow_dispatch' would skip it — and since the pretested output would then be empty, the existing '' != '1' condition already yields the same run-anyway result with no change to line 138. Minor, but the dispatch path is the one an operator uses while master is red and waiting on it.

Strengths

  • The always() comment at lines 127-136 is the right kind of comment: it explains the invisible failure mode (implicit success() on needs), enumerates the concrete triggers, and states the consequence of getting it wrong. The finding above is a refinement of the mechanism, not a disagreement with the reasoning — and the reasoning is what makes the refinement cheap to apply.
  • The SCOPE block is an unusually honest header. Most workflows named after a guarantee quietly over-promise; this one states what it does not cover, prices the alternative, and gives a revisit trigger.
  • The concurrency fix keys on github.event_name (line 55) with the rationale inline, correctly preserving push-drain collapsing while isolating operator dispatches.
  • gh on arc-light is now backed by a named in-repo precedent (lines 70-72) rather than an assumption.
  • github.sha and github.repository reach the script through env: (lines 80-83) instead of ${{ }} interpolation into the shell body — the correct pattern, and one this repo does not apply uniformly elsewhere.
  • The workflow-path filter at lines 104-106 remains the subtle detail most implementations miss, and the empirical head_sha chain at lines 87-92 is real verification rather than an assertion.

Recommended Action

  1. No Critical issues.
  2. Address the always()!cancelled() change this cycle — one line plus a comment touch-up, and it restores the cancellation semantics the cost model at lines 29-34 assumes.
  3. Consider the two Suggestions opportunistically; the gate-race one is worth a quick measurement since it determines whether the gate pays for itself.

Ally review of de9df20. always() is true even when the run is CANCELLED,
and job-level if: is evaluated at dispatch time, so during a bulk drain
(12 commits in ~3 min against a gate that takes seconds) every superseded
run would still dispatch the 6-leg matrix at timeout-minutes: 90 each --
up to ~72 pods for one drain instead of 6, onto the pool the SCOPE block
explicitly budgets against, during the exact event this workflow watches.

!cancelled() keeps the fail-closed property the previous commit added (it
excludes only cancellation, not failure) without resurrecting superseded
runs. Wrapped in ${{ }} because a YAML scalar starting with ! is a tag
indicator and will not parse bare.

Co-Authored-By: Claude <noreply@anthropic.com>
@allyblockcast

allyblockcast Bot commented Aug 16, 2026

Copy link
Copy Markdown
Author

Both review rounds addressed at 3ba636ff. Thank you — the always() finding is a real regression I introduced and would not have caught myself.

Important — always()!cancelled(): fixed, and the diagnosis is exactly right

always() is true even when the run is cancelled, and job-level if: is evaluated at dispatch time. So during a bulk drain — the very scenario the concurrency block exists for — each superseded run would still dispatch the 6-leg matrix at timeout-minutes: 90, up to ~72 pods for one drain instead of 6, onto the pool the SCOPE block budgets against, during the event this workflow is watching. I reached for always() to restore fail-closed and silently traded away the cost model that justifies the whole design.

Applied if: ${{ !cancelled() && (...) }}, including the ${{ }} wrapper — confirmed a bare ! scalar is a YAML tag indicator. Verified the fail-closed property survives: !cancelled() excludes only cancellation, not failure, so on a gate job failure pretested is still empty, '' != '1' still holds, and the suite still runs. The comment now explains the always()-vs-!cancelled() distinction rather than asserting always() is load-bearing.

Suggestion 1 (gate race) — measured, and it is not a problem

You were right that this determines whether the gate pays for itself, so I measured rather than reasoned. For the 7 most recent queue landings, comparing the pr.yml merge_group run's completion to the PR's merged_at:

PR run completed merged lead
#1387 11:13:50 11:14:06 +16s
#1385 12:56:22 12:56:41 +19s
#1381 11:53:15 11:53:28 +13s
#1380 02:26:18 02:26:31 +13s
#1379 00:29:19 00:29:32 +13s
#1377 03:43:53 03:44:16 +23s
#1371 14:14:28 14:14:49 +21s

7/7 complete before the merge, consistently 13–23s ahead — which makes sense mechanically: the merge is caused by the merge_group checks passing, so completion necessarily precedes the push. The gate sees conclusion: success at push time and the ~63.5% saving is real, not theoretical. (#1382 in the same window has no queue run at all — a direct merge, i.e. the case this workflow is for.)

Suggestion 2 (skip gate on workflow_dispatch) — declining, deliberately

Your reasoning is correct, including that the empty pretested would flow through the existing condition unchanged. I am leaving it: the gain is ~30s on a hand-triggered path, and the cost is that the workflow's control flow then depends on skip-propagation through needs interacting with a status-check function — a subtlety that is easy to misread later, on the one path an operator uses while master is red. Happy to take it if you feel strongly; I would rather the dispatch path stay boring.

Suggestion 3 (notification routing) — agreed, out of scope here

A red push-run notifying only the pushing actor is a genuine gap given the failure mode is company-wide queue blockage. That is alert routing rather than detection, and it wants the same treatment as the rest of our CI alerting; noted on BLO-27871 rather than bolted on here.

@allyblockcast allyblockcast Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ally — Consolidated PR Review

Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: 3ba636f

Looks good. The one prior blocker is fixed, and fixed precisely — the change is the single if: line plus the reasoning for it, with no incidental drift. I re-derived the truth table rather than taking the comment's word for it, and it holds in all four states: gate failure!cancelled() true, pretested empty, '' != '1' true → suite runs (fail-closed preserved); run cancelled → false → suite skipped (the cost regression closed); gate success → gate output decides; dispatch → runs regardless.

Critical Issues (0)

Important Issues (0)

Prior Findings Dispositioned (1)

  • prior:de9df20 important 1 — fixed — .github/workflows/master-health.yml:152always() is replaced by ${{ !cancelled() && (...) }}, exactly the rewrite the finding asked for, including the ${{ }} wrapper. I verified the parse hazard the finding warned about is genuinely avoided rather than merely commented: the raw scalar at line 152 begins ${{, not !, so it is a plain scalar and no YAML tag indicator is in play (pr.yml:662 is in-repo precedent for the same form). Cancellation no longer resurrects superseded runs, and the fail-closed path the previous fix established is untouched.

Suggestions (1)

  • [pr-review-toolkit] The two suggestions from the previous round are unaddressed and still stand as written — the gate-race question at .github/workflows/master-health.yml:106 (conclusion == "success" read at push time, which decides whether the gate pays for itself) and the redundant gate pod on workflow_dispatch at .github/workflows/master-health.yml:64. Deliberately not re-expanded here; they are on record in the de9df208 review and neither blocks.

Strengths

  • The comment at lines 137-149 does the thing that makes this class of bug non-recurring: it states the distinction is "a real distinction here rather than style," names the exact mechanism (always() is true even when cancelled; job-level if: evaluates at dispatch time), prices the consequence in concrete units (6 legs × timeout-minutes: 90 per cancelled run), and — unusually — documents the YAML tag-indicator trap that makes the naive one-token fix fail. A reader who wants to "simplify" this back to always() has to argue with the reasoning first.
  • The edit is minimal in the right way. Comparing de9df208...3ba636ff, the only functional change is that one line; the matrix, gate script, permissions, and concurrency block are untouched. A fix that also tidies unrelated lines is a fix that is harder to review and harder to revert.
  • Re-verified at this head: the matrix is still byte-identical to pr.yml:522-547, and the PR-only "Restore regenerated PR lockfile" step (pr.yml:558-564, gated on needs.policy.outputs.lockfile_regenerated) remains correctly omitted rather than copied along with it.
  • The gate's ordering property is stronger than the comment claims credit for: if a direct merge lands while a PR is mid-queue, GitHub rebuilds the merge group on the new base, so either the landed SHA matches a green pr.yml merge_group run that already covered both commits, or it does not match and the suite runs. Both branches are safe — the optimisation has no window where an untested commit is masked by a later queued one.

Recommended Action

  1. No Critical issues.
  2. No Important issues — the prior blocker is resolved and nothing new was introduced.
  3. Consider the two carried-forward suggestions opportunistically; the gate-race measurement is the one with real information value, since it determines whether the gate earns its pod.

@allyblockcast
allyblockcast Bot added this pull request to the merge queue Aug 16, 2026
Merged via the queue into master with commit 98dc698 Aug 16, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants