Skip to content

Arm 4 (present) is RED on every live PR and required by nothing — no PR-review receipt has landed since #3491 #3818

Closed as not planned

Description

@noahgift

Found by aprender-c7, 2026-09-22, while reading batch-1's CI (#3772 @ 935f2cc88). Not a batch-1 defect — measured across the fleet.

The measurement

present (job present in .github/workflows/pr-review-quorum.yml, Arm 4, scripts/check_pr_review_arm4.sh) fails on every open PR sampled: #3772, #3814, #3808, #3802. The failure is identical and is about absence, not content:

A1  .github/pr-review.pub present (RWTeGb4p8Ma1IqgL...)
A2  no receipt directory at .../evidence/pr-review/3772
    S6.3: a missing receipt is RED, not skipped. S8 fixes
    receipt_presence at 100% with no ratchet.
check_pr_review_arm4.sh: FAIL - see the arm above.

Base rate from the tree (origin/main), because one red PR is an anecdote:

fact value
PRs that have ever carried a receipt directory 24
of those, above the grandfather line PR_REVIEW_CUTOFF=2840 22
newest PR with a receipt #3491, landed 2026-09-20 (237fbc32f)
PRs merged above #3491 since 45
open PRs today 58
receipts above #3491 0

And it is required by nothing, under either mechanism — both were read, not one:

mechanism required contexts
branch protection on main ci / gate, workspace-test (strict: true)
ruleset 13878864 "Green Main" gate
ruleset 19814559 "workspace-test" workspace-test

present is in none of them, and gate no longer needs: it (that was the deliberate PP-066 C0-5 / PRQ-013 move, so a PR could not define the check that judged its own receipt).

Why this is a defect and not just an empty queue

This is the mirror image of the class being closed all week. Not a green badge over nothing — a red one nobody reads. Both are gate theater: a check that fires on 100% of pull requests carries exactly as much information as one that fires on 0%, and a reviewer who sees present red on every PR learns to scroll past the row where a real receipt failure would appear.

The workflow's own header states the intent against which the tree can be measured: it "arms FORWARD", grandfathering below the cutoff because "the measured receipt rate on the day this landed was 1 across 24 open PRs — arming it retroactively is not a ratchet, it is an outage", and receipt_presence is "fixed at 100% with no ratchet". The forward arming stopped landing after #3491. The same argument that justified cutoff 2840 now applies to the window above it.

Neither producing side fails, by design, which is why this went unnoticed:

  • ci.yml pr-review-sign exits 0 when there is nothing to sign: "no receipt directory $root — nothing to sign. The review is still owed; the S13.11 shadow lane records its absence."
  • pr-review-shadow invokes the arm with --explain and records the verdict; it is shadow-only and in no needs: list (PR-REVIEW-SKILL-002 v2 §13.11, still not armed).

So the only surface that says "the review is owed" is a check nothing requires, on every PR at once.

Probable cause, stated as a hypothesis and not as a finding: the fleet's review evidence moved. docs/audits/ carries 69 quorum-*.json artifacts on main, most recent 2026-09-21 (a9502d992); evidence/pr-review/ carries 24 PR directories, most recent #3491 on 2026-09-20. Two mechanisms answer "was this diff reviewed", and only one of them is still being fed. Confirming or refuting that is step 1 of any fix — do not assume it.

done_when

Exactly one of these, with its falsifier. Not "Arm 4 is green".

Option A — restore production (RECOMMENDED). Every PR above the cutoff carries evidence/pr-review/<pr>/<head sha>/receipt.intoto.jsonl, produced by whatever process is now the review of record, and the existing signer signs it.

  • Falsifier: a PR opened with no receipt turns present RED (it already does — that row must stay RED, so the mutation is the inverse: delete the receipt from a PR that has one and show the row go RED, and point the receipt at a stale head sha and show it go RED), and after the fix a freshly opened PR has a receipt directory within one CI run without a human writing it.
  • Why recommended: it is the only option under which the arm carries information again. Every other path makes the row quieter without making it true.

Option B — advance the cutoff to where production actually resumes (FALLBACK, only if A is refused). PR_REVIEW_CUTOFF moves from 2840 to the first PR number from which receipts genuinely land; below it, absence is reported and not RED; above it, unchanged.

  • Falsifier: check_pr_review_arm4.sh already ships the two-polarity cutoff case table (scripts/check_pr_review_arm4.sh:341-347 — the same receiptless tree passes below the cutoff and fails above it). That table must be re-run at the NEW number, both polarities, per the standing rule that extending a guard's scope requires re-mutating in the new scope. A present-but-tampered receipt stays RED at any PR number (flip a byte in receipt.intoto.jsonl → RED).
  • Why only a fallback: advancing the cutoff without restoring production converts a red-nobody-reads into a green-that-means-nothing. That is trading one theater for the other, and it must be recorded as an accepted loss of coverage rather than as a fix.

Explicitly out of scope

Do not make present a required check. A gate red on 100% of live PRs must not become blocking; arming it in this state blocks all 58 open PRs at once, which is the outage the cutoff comment already describes from experience. Whichever option lands, present stays advisory until its red rate reflects real absences.

Not a 0.69.1 blocker, deliberately

Filed against 0.70.0. It blocks nothing under either mechanism today, and fixing a reporting-only gate during a release train is how release trains slip — the same call f0 made on #3805. 0.69.1 ships with present red on its PRs and this issue as the record of why.

Refs #2982 (PP-066 C0-5 / PRQ-013, the move that made this check base-owned)

Activity

  1. added this to the 0.70.0 milestone on Sep 22, 2026
  2. modified the milestones: 0.70.0, 0.70.1 on Sep 24, 2026
  3. noahgift commented on Sep 24, 2026

    @noahgift
    MemberAuthor

    Milestone 0.70.0 → 0.70.1 (gate triage). 0.70.0 now holds only the operator's release gate: "FULL ontology spec and all aprender binary working" + "0.70 to crates.io" (ONT-001, every [[bin]] build+smoke, the publish cascade), plus P0s and operator-ruled rows. This issue isn't needed for any of those. Evidence: evidence/m070-gate-triage-1835.md. If that's wrong, move it back to 0.70.0 and say which gate it serves.

  4. noahgift commented on Sep 25, 2026

    @noahgift
    MemberAuthor

    Parked by APR-EPIC-001: over S1 budget (rank 89/163). Reopen = pull. Applied by aprender-d1: claude+agy both said close, apr shadow row recorded (handoff/close-quorum-2026-09-25.json).

  5. modified the milestones: 0.70.1, backlog on Sep 25, 2026
  6. added
    parkedClosed over epic budget (APR-EPIC-001 rule 5). Reopen = pull.
    on Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparkedClosed over epic budget (APR-EPIC-001 rule 5). Reopen = pull.

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions