Development record
external-review.yml computes its approver tally with 'gh api .../reviews --paginate --jq' where --jq runs per API page (not across the full set; --slurp is incompatible with --jq), and no per_page is set so pages are 30 — so the 'latest state per reviewer wins' reduction the comment promises fails once reviews span a page: a stale page-1 APPROVED survives a later page-2 CHANGES_REQUESTED, and a straddling double-approval is counted twice. Fail-open on a required security gate. Not fixed autonomously: required-check workflow that cannot be validated without running Actions
external-review.yml computes its approver tally with 'gh api .../reviews --paginate --jq' where --jq runs per API page (not across the full set; --slurp is incompatible with --jq), and no per_page is set so pages are 30 — so the 'latest state per reviewer wins' reduction the comment promises fails once reviews span a page: a stale page-1 APPROVED survives a later page-2 CHANGES_REQUESTED, and a straddling double-approval is counted twice. Fail-open on a required security gate. Not fixed autonomously: required-check workflow that cannot be validated without running Actions
Evidence
.github/workflows/external-review.yml—gh api "…/pulls/$PR/reviews" --paginate --jq '… | group_by(.user.login) | map(max_by(.submitted_at)) | map(select(.state=="APPROVED"))'.gh --paginateapplies--jqper page (and--slurpis incompatible with--jq), and noper_pageis set, so pagination is at 30. The "latest state per reviewer wins" comment above it does not hold once reviews span a page: a page-1 APPROVED survives a page-2 CHANGES_REQUESTED, and a straddling double-approval counts twice.- Required check per
.abcd/work/rulesets/main-protection.json. Direction is fail-open on a security gate. Landed today (iss-281).
Adversarial review
CONFIRMED (substantive, latent — needs >30 review entries on one external PR) by an
independent refuter. Proposed fix (NOT applied this round): split slurp and jq —
gh api … --paginate --slurp | jq '[.[][] | …] | group_by(...) | …'. Left open: modifying a
required-check workflow cannot be validated without a real Actions run.
Grounds
- pursued: an approval superseded on a later page does not count, and a reviewer counts once however many pages their reviews span; shown wrong by an external PR going green on a withdrawn or double-counted approval
Frontmatter
| id | iss-301 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-301-external-review-yml-computes-its.md
open on GitHub ↗ · commit history ↗
mentions4
- dcn-26081900000000032026-08-19 — bughunt round 1 (branch bughunt-b/round-1): captured iss-291..iss-304 and fixed
- iss-281Externally submitted PRs and issues must be reviewed by at least two invited collaborators (hard rule, maintainer decision 2026-08-19). PR half: enforceable as a required status check counting approvals from collaborators with role triage or above, running on pull_request_target so a fork cannot neuter it. Issues half: GitHub issues carry no native review gate — ledger captures land via PRs and inherit the PR rule; tracker issues rely on intake S1 process until a mechanism exists
- iss-355a batched merge-queue push makes github.sha the batch tip, so auto-release tags the wrong commit and release.yml's HEAD-caret-2-caret receipt derivation resolves an unrelated PR's commit whenever the release roll is not the last entry in its queue batch; the ancestry guard passes and the run wedges after the immutable tag, the iss-326 outcome by a route itd-93's pre-merge check cannot close because batch composition is decided by the queue
- iss-2609120452071388Reported from a downstream repository using abcd, where `abcd capture` (bare,