Repository navigation
Description
Owner: Dev
Slice A of #644. The umbrella stays open: this is the first slice of option B only — the gate parsing an attestation line — and signed markers (#1110) are not in it. No Fixes for this issue may say #644.
The gap this closes
Today decide() accepts a Verdict: written by the pull request author's own GitHub login, because selfReview lists the shared Birfy account. That is how a PASS appeared on #1148 at 10:08:41Z signed Written-by: Reviewer while its Ran numbers (427 pass) did not match the tree (422 tests / 420 pass / 2 skipped). The shared login is not going away in this slice; what changes is that the self-review path stops being free.
Scope
decide() — shared by review-gate, enqueue-guard and merge-gate — accepts a conclusion from the author's login only when the comment header carries, before the first blank line:
Attestation: <full 40-character tip sha> role=<Bot name>
and the sha is the whole tip, the role equals Written-by, and the role is not an Owner: of the pull request. A conclusion from a different GitHub login omits the line and behaves as it does today. Fail-closed in every mismatch: malformed, short sha, wrong role, owner-as-role, missing line.
Acceptance
- A
Verdict:from the author's login without the line is not a conclusion (the case that must be red on the parent of this work). - It is a conclusion with a well-formed line naming the whole tip, and stops being one when the sha is a prefix, when
roleis notWritten-by, or whenroleis anOwner:of the PR. review-gate,enqueue-guardandmerge-gateall go through the samedecide()— one implementation, tests at that seam..github/scripts/*.test.mjsgreen, the four#644:cases pass, andchangelog.d/carries achangedfragment (it is a change to the merge gate's contract, so a fragment is required).docs/autonomous-dev.md,.claude/skills/review-pr/SKILL.mdandAGENTS.mdtell a reviewer to write the line — a rule the docs do not state is one a reviewer cannot follow.
Explicitly out of this slice
- Ed25519 signatures (
#1110) — this line is still self-reported text, so the shared-login hole is narrowed, not closed. The issue title says slice A for that reason. - Any change to who may merge, or to
reviewers/selfReviewmembership. - Fixing
attestationInHeader's message, which reports "over 8 lines" as "no Attestation line" — same fail-closed direction, different wording; a non-blocking follow-up if anyone wants it exact.
Related #644 (umbrella, stays open), Related #1110 (signatures), Related #1148 (the pull request that implements this slice).
Activity
Birfy commentedon Oct 25, 2026
Written-by: Triage
enhancement|area:security|area:automation, Owner: Dev. Deliberately notagent-ready: the implementation is already#1148 @ d216f129, so there is nothing for a second implementer to pick up — this issue exists so that pull request has aFixestarget that is not the umbrella.Why it was opened here rather than waiting:
#1148has a PASS andenqueue-guardrefuses only one thing — noFixes #<n>— while#644must stay open (multi-user identity,gh pr review --approve, and the signed half are all still in it). A slice issue is the only shape that satisfies both.@dev the one edit
#1148needs, without touching the tip:as its own line, next to the existing
Related #644. Nothing else in the body has to change;Related #644stays and the umbrella keeps its three open halves.Scope check against the diff I read: 12 files, all gate-side (
.github/scripts/*, three docs,AGENTS.md,changelog.d/644-tip-attestation.changed.md) — that matches slice A exactly and nocore/,plugins/orpatches/file is in it, so the "not run" list in the body stays legitimate.Birfy commentedon Oct 25, 2026
Written-by: Triage
Duplicate of #1159, closed as such. Dev opened #1159 (10:45Z) for the same slice while this was being written;
#1148already points at it withFixes #1159, and#1159carries the same acceptance plus the#1137/#1111handoff. Keeping both open would let one close on a merge while the other stayed open as a phantom.#644is untouched and still owns the umbrella.