Summary
pr-governance.yml produces two check runs, and only one of them carries the "not applicable" signal its escape paths intend.
| Check |
Created by |
Escape path result |
PR Governance |
the workflow, via github.rest.checks.create in publish() |
neutral |
Canonical issue and evidence |
GitHub, for the job itself |
success |
On an escape path, publish("neutral", …) does not call core.setFailed, so the job exits 0 and GitHub records its check as success. The neutral conclusion exists only on the custom PR Governance check.
Net effect: a PR that was never evaluated against the canonical delivery contract reports success on Canonical issue and evidence — indistinguishable from a PR that satisfied it.
Verified
Two independent PRs on the draft escape path:
PR #1423 (own PR, head e08ac36, draft):
PR Governance -> neutral
Canonical issue and evidence -> success
PR #1000 (Dependabot, draft):
PR Governance -> neutral
Canonical issue and evidence -> success
Pre-existing, not introduced by #1423
This is inherited from the if (pr.draft) escape at pr-governance.yml:49, which has always behaved this way. #1423 adds a Dependabot escape with the same shape, so it inherits the topology — it does not create it, widen it, or open a fail-open path for non-exempt authors. Raised by CodeRabbit while reviewing #1423 and split out here rather than scope-creeping that PR.
Why it matters
MERGE_POLICY.md gate 2 governs which contexts are required in branch protection. If Canonical issue and evidence is the required context, then every draft and every Dependabot PR reports a green required check while the contract went unevaluated. That is the same defect class the policy file exists to name: a check whose green does not mean what a reader assumes.
The exemptions themselves are correct — neither drafts nor Dependabot can meaningfully satisfy the contract. The problem is that the honest neutral lands on a check nobody is necessarily requiring.
Options
- Require
PR Governance rather than Canonical issue and evidence in branch protection, and say so in MERGE_POLICY.md. Smallest change; the custom check already carries the correct three-state signal (success / neutral / failure). Probably the right answer.
- Make the job itself skip on escape paths via a job-level
if:, so the job check reports skipped. Harder — the draft flag is available in the event payload, but the author check is currently made inside the script.
- Accept and document. Lowest effort, but leaves the misleading green in place.
Acceptance criteria
Summary
pr-governance.ymlproduces two check runs, and only one of them carries the "not applicable" signal its escape paths intend.PR Governancegithub.rest.checks.createinpublish()neutralCanonical issue and evidencesuccessOn an escape path,
publish("neutral", …)does not callcore.setFailed, so the job exits 0 and GitHub records its check assuccess. Theneutralconclusion exists only on the customPR Governancecheck.Net effect: a PR that was never evaluated against the canonical delivery contract reports
successonCanonical issue and evidence— indistinguishable from a PR that satisfied it.Verified
Two independent PRs on the draft escape path:
Pre-existing, not introduced by #1423
This is inherited from the
if (pr.draft)escape atpr-governance.yml:49, which has always behaved this way. #1423 adds a Dependabot escape with the same shape, so it inherits the topology — it does not create it, widen it, or open a fail-open path for non-exempt authors. Raised by CodeRabbit while reviewing #1423 and split out here rather than scope-creeping that PR.Why it matters
MERGE_POLICY.mdgate 2 governs which contexts are required in branch protection. IfCanonical issue and evidenceis the required context, then every draft and every Dependabot PR reports a green required check while the contract went unevaluated. That is the same defect class the policy file exists to name: a check whose green does not mean what a reader assumes.The exemptions themselves are correct — neither drafts nor Dependabot can meaningfully satisfy the contract. The problem is that the honest
neutrallands on a check nobody is necessarily requiring.Options
PR Governancerather thanCanonical issue and evidencein branch protection, and say so inMERGE_POLICY.md. Smallest change; the custom check already carries the correct three-state signal (success/neutral/failure). Probably the right answer.if:, so the job check reportsskipped. Harder — the draft flag is available in the event payload, but the author check is currently made inside the script.Acceptance criteria
MERGE_POLICY.mdnames whichever context is authoritative and states what its green means.