Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: a91e62dd206541bbab9c6e2898d04642
Branch: dev/4-pass-label-writer-case
Base: d400edb
At: 2026-11-05T14:32:45Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
What happens
pass-label matches the PASS writer case-sensitively, the gates do not, so a PASS the gates accept can leave no trace at all.
.github/scripts/pass-label.mjs:45:
if (!report.writer || !writers.includes(report.writer)) return nullwriters is the plain array from .github/agent/review-policy.json, and includes compares exact strings. review-gate.mjs:77-85 builds new Set(policy.reviewers.map(l => l.toLowerCase())) and compares name.toLowerCase(), and merge-gate imports the same decide. So Written-by: reviewer (or dev4) against a roster entry Reviewer is a valid conclusion for the gates but verdictOf returns null — no pass label, no comment, no notification.
The stranger path does not rescue it either: strangerPassOf (:74-75) lowercases both sides, so the same writer counts as listed and returns null — the PR is silently unlabelled where #739 promises a pass record.
Reproduction
Clean d400edb74798b71e233eccd46f221eaef782ff5d, only a new case added to .github/scripts/pass-label.test.mjs:
not ok 3 - #739: a writer matches the way the gates match it, whatever its case
error: 'reviewer is a listed name in another case'
expected: true
actual: ~
# tests 12 / # pass 11 / # fail 1
Run: node --test .github/scripts/pass-label.test.mjs.
Expected
One comparison rule, used in both places: a name is a listed writer when it matches a roster entry case-insensitively (isListedWriter(writers, name)), so verdictOf labels the PASS that review-gate already accepts and strangerPassOf stays quiet for the same name. Nothing widens: a name that is not in the roster in any case still yields null (negative controls: reviewer3, Reviewer Extra).
Scope
.github/scripts/pass-label.mjs— one exported helper (≈+3/−2),verdictOfandstrangerPassOfboth use it so the two cannot drift again..github/scripts/pass-label.test.mjs— the case case plus the two negative controls (≈+16/−0).changelog.d/<this issue>-pass-label-writer-case.fixed.md.- No generated artifact:
core/client.js,patches/ds-bot/**and their mirrors are untouched.
Tier: T2 (.github/scripts/**, changelog.d/**).
Duplicate check
Searched before filing: pass-label → #739 (closed, the feature), #797/#760 (closed, its implementation — lowercased only the stranger path), #801 (closed, review-body PASS); pass label case in:title → 0; no open issue or PR touches the verdictOf writer comparison.
Done when
The new case is red on the base and green with the fix, the .github/scripts suite is 669/669, the negative controls still yield null, and arch-docs reports no changed files for this PR.
Activity
HugoXK commentedon Nov 5, 2026
Claim-Id: a91e62dd206541bbab9c6e2898d04642
Branch: dev/4-pass-label-writer-case
Base: main (
d400edb74798b71e233eccd46f221eaef782ff5d)Flight plan: one PR (
Fixes #2544) fromdev/4-pass-label-writer-case, ready,maintainer_can_modify: true, red-first evidence in the body. Bug, T2 (.github/scripts/**+changelog.d/**).HugoXK commentedon Nov 5, 2026
Written-by: FlyBot Lead
Evidence for the maintainers, left here because we are not changing a gate file today:
#2547was frozen atbc0e72eb07df045bdbe1232a5c870e8eca41f765and its body no longer asks for a signature. Everything below is read from livemain(276042f828bbf21716d93e1901619eab9f4e794c) as it stands.The asymmetry, three sites:
So a report written
Written-by: reviewer(ordev4) against a roster entryRevieweris a conclusion forreview-gateandmerge-gate, butverdictOfreturnsnull— nopasslabel and no comment — whilestrangerPassOfcalls the same name listed and stays silent.#739promises thepassrecord in exactly the case that goes quiet here.Red first (clean base, only the new case in
.github/scripts/pass-label.test.mjs):Fixed locally:
pass-label.mjs+3/−2(oneisListedWriter(writers, name)used by both paths), test+16/−0,.github/scriptssuite 669/669, negative controlsreviewer3andReviewer Extrastillnull.Why it is not in our pull request:
.github/scripts/pass-label.mjsis a gate file inpolicy/gates.json, sopolicy-signrefuses a change to it without a signed comment from another person naming the tip — its own words on#2547:policy-sign refused (#2547): a gate file changed (.github/scripts/pass-label.mjs), and the body carries no 'Policy-sign:' line naming a comment. That signature is the maintainers' decision, not ours to arrange inside a sprint; the change belongs in your file, with the roster test you already keep.The local branch
dev/4-pass-label-writer-caseand the PR#2547stay as they are (frozen, not merged); nothing is pushed further and no workflow is asked for.