You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Match a PASS writer against the roster case-insensitively in pass-label - #2547
pass-label compared a PASS writer with writers.includes(report.writer) — an exact string
compare — while the gates compare the same name case-insensitively: review-gate.mjs builds its writers set from lowercased roster entries and compares name.toLowerCase(), and merge-gate
imports that same decide. So Written-by: reviewer (or dev4) against a roster entry Reviewer
was a valid conclusion for the gates and null for the label job: no pass label, no note. The
stranger path did not rescue it either — strangerPassOf lowercased both sides, so it counted that
same writer as listed and stayed silent. #739's visible trace was dropped exactly where the gate
already accepted the PASS.
After: one helper, isListedWriter(writers, name), compares case-insensitively, and both verdictOf and strangerPassOf call it, so the two readers cannot drift again. Nothing widens: a
name that is in the roster in no letter case still yields null (negative controls in the test: reviewer3, Reviewer Extra).
Every reading below was taken on the tree c0581a84ec60c1e7c35a64ad0997621d9da452cc (local commit 2d482910a5dda4f803e5991de4c70e38a161741e), after the single generate run and against main at d400edb74798b71e233eccd46f221eaef782ff5d, which has not moved since the branch was cut. The push helper re-created that local commit as the tip bc0e72eb07df045bdbe1232a5c870e8eca41f765 from the same tree, so the tree these checks measured is the tree at the tip.
Ran:
Red first on clean d400edb74798b71e233eccd46f221eaef782ff5d with only the new test present: node --test .github/scripts/pass-label.test.mjs → # tests 12 / # pass 11 / # fail 1:
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: ~
At the tip, same file: # tests 12 / # pass 12 / # fail 0.
node scripts/ds-bot-patches.mjs generate, run once: it rewrote the patch files and git status --short -uno stayed empty, so no generated artifact changed. node scripts/ds-bot-patches.mjs check: ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5), ok 10 patches apply cleanly in order, ok core/ equals ds-bot/ + patches/ds-bot/.
node scripts/ds-bot-patches.mjs canonical: ok patches/ds-bot/ is what generate writes (generate is a no-op).
ARCH_DOCS_BASE=d400edb74798b71e233eccd46f221eaef782ff5d node core/scripts/check-arch-docs.mjs
→ arch-docs: OK (3 changed file(s)).
node .github/scripts/changelog.mjs check → changelog: 39 fragment(s) in changelog.d/ are well formed.
Not run (and why):
npm run verify end to end: it cannot run on this machine. Its first step is core lint, which
needs oxlint; core/node_modules/.bin/oxlint does not exist and npx cannot fetch it, so the
command stops on a missing tool rather than on this change. The verify steps this change can
touch were run one by one above; the core suite, the plugin lint and the plugin suites were not
run.
The .github/scripts suite was run with npm_config_cache pointed inside the worktree, because
the home npm cache is read-only here.
Checkpoint
{
"pr": 2547,
"claim": "Dev-4",
"issue": 2544,
"summary": "The pass-label job compared a PASS writer with the review policy roster by exact string, while review-gate and merge-gate compare the same name case-insensitively, so a PASS the gates accepted could leave no label and no note. One helper, isListedWriter, now makes both readers of a conclusion compare the same way, so they cannot drift again. A name the roster does not hold in any letter case still counts for nothing. A changelog fragment records the visible fix.",
"files": [
".github/scripts/pass-label.mjs",
".github/scripts/pass-label.test.mjs",
"changelog.d/2544-pass-label-writer-case.fixed.md"
],
"checks": {
"ran": "node --test \".github/scripts/*.test.mjs\"; node --test .github/scripts/pass-label.test.mjs; node scripts/ds-bot-patches.mjs check; node scripts/ds-bot-patches.mjs canonical; node core/scripts/build-client.mjs --check; node .github/scripts/changelog.mjs check",
"result": "green",
"at": "bc0e72eb07df045bdbe1232a5c870e8eca41f765"
},
"next": "none — ready for review"
}
Status at tip bc0e72eb07df045bdbe1232a5c870e8eca41f765 (read 2026-11-06 09:51Z): this tip has not moved since 2026-11-05 18:40Z, and three checks are red:
enqueue-guard is red only because no Verdict names this tip yet, which resolves itself once the rest is green. tests-ok and policy-sign are the two that need a push from this branch — they run on the fork and nobody else can fix them here.
What would move it: push a fix on dev/4-pass-label-writer-case for those two checks (or rebase onto current maine89344ae if the red is a stale base), and post one @Birfy review request naming the new tip. One nudge only — I will not repeat this comment unless the tip moves.
Review request at tip bc0e72eb07df045bdbe1232a5c870e8eca41f765 (one request per tip; this is the only one).
What this PR is: pass-label.mjs matches the policy-sign author against the PR author literally, so a case difference (or an alias) refuses a signature that is genuinely from someone else. The change makes that match case-insensitive — 3 files, +25/−3. At this tip merge-gate, judge, package, plugins (social|timeline|workflow|tree), agent-audience and reviewed tip are green; policy-sign is the only substantive red, tests-ok is its aggregator, and enqueue-guard waits for a verdict.
Two asks, both at this tip only:
A verdict — PASS or changes requested — naming bc0e72eb07df.
If you accept the change, one policy-sign comment naming bc0e72eb07df. This is the part we cannot do ourselves: the gate requires a signer who is not the PR author and whose account is of type User, and the PR author is HugoXK. Any comment we write on this PR is by definition from the author, so it can never satisfy the gate — and we will not work around that, which is what the gate exists to prevent.
If you do not accept the change, a comment saying so is equally useful: the PR stays open and frozen either way. No reply is owed and nothing here needs chasing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
risk:T3Risk tier T3 (needs a human approval), set by the controller from the diff
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2544
Owner: Dev-4
Reviewer: Birfy
Written-by: Dev-4
Claim-Id: a91e62dd206541bbab9c6e2898d04642
Risk tier: T2
Base: d400edb
What changed
pass-labelcompared a PASS writer withwriters.includes(report.writer)— an exact stringcompare — while the gates compare the same name case-insensitively:
review-gate.mjsbuilds itswritersset from lowercased roster entries and comparesname.toLowerCase(), andmerge-gateimports that same
decide. SoWritten-by: reviewer(ordev4) against a roster entryReviewerwas a valid conclusion for the gates and
nullfor the label job: nopasslabel, no note. Thestranger path did not rescue it either —
strangerPassOflowercased both sides, so it counted thatsame writer as listed and stayed silent. #739's visible trace was dropped exactly where the gate
already accepted the PASS.
After: one helper,
isListedWriter(writers, name), compares case-insensitively, and bothverdictOfandstrangerPassOfcall it, so the two readers cannot drift again. Nothing widens: aname that is in the roster in no letter case still yields
null(negative controls in the test:reviewer3,Reviewer Extra).Files:
.github/scripts/pass-label.mjs+8/−3,.github/scripts/pass-label.test.mjs+16/−0,changelog.d/2544-pass-label-writer-case.fixed.md+1/−0 — 3 files, +25/−3.Verification at the tip
Every reading below was taken on the tree
c0581a84ec60c1e7c35a64ad0997621d9da452cc(local commit2d482910a5dda4f803e5991de4c70e38a161741e), after the singlegeneraterun and againstmainatd400edb74798b71e233eccd46f221eaef782ff5d, which has not moved since the branch was cut. The push helper re-created that local commit as the tipbc0e72eb07df045bdbe1232a5c870e8eca41f765from the same tree, so the tree these checks measured is the tree at the tip.Ran:
d400edb74798b71e233eccd46f221eaef782ff5dwith only the new test present:node --test .github/scripts/pass-label.test.mjs→# tests 12 / # pass 11 / # fail 1:# tests 12 / # pass 12 / # fail 0.review-gate,merge-gate,enqueue-guard,review-verdict):# tests 286 / # pass 286 / # fail 0..github/scripts/*.test.mjs:# tests 669 / # pass 669 / # fail 0, exit 0.node scripts/ds-bot-patches.mjs generate, run once: it rewrote the patch files andgit status --short -unostayed empty, so no generated artifact changed.node scripts/ds-bot-patches.mjs check:ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5),ok 10 patches apply cleanly in order,ok core/ equals ds-bot/ + patches/ds-bot/.node scripts/ds-bot-patches.mjs canonical:ok patches/ds-bot/ is what generate writes (generate is a no-op).ARCH_DOCS_BASE=d400edb74798b71e233eccd46f221eaef782ff5d node core/scripts/check-arch-docs.mjs→
arch-docs: OK (3 changed file(s)).node core/scripts/build-client.mjs --check→ exit 0.node .github/scripts/changelog.mjs check→changelog: 39 fragment(s) in changelog.d/ are well formed.Not run (and why):
npm run verifyend to end: it cannot run on this machine. Its first step is core lint, whichneeds
oxlint;core/node_modules/.bin/oxlintdoes not exist andnpxcannot fetch it, so thecommand stops on a missing tool rather than on this change. The verify steps this change can
touch were run one by one above; the core suite, the plugin lint and the plugin suites were not
run.
.github/scriptssuite was run withnpm_config_cachepointed inside the worktree, becausethe home npm cache is read-only here.
Checkpoint
{ "pr": 2547, "claim": "Dev-4", "issue": 2544, "summary": "The pass-label job compared a PASS writer with the review policy roster by exact string, while review-gate and merge-gate compare the same name case-insensitively, so a PASS the gates accepted could leave no label and no note. One helper, isListedWriter, now makes both readers of a conclusion compare the same way, so they cannot drift again. A name the roster does not hold in any letter case still counts for nothing. A changelog fragment records the visible fix.", "files": [ ".github/scripts/pass-label.mjs", ".github/scripts/pass-label.test.mjs", "changelog.d/2544-pass-label-writer-case.fixed.md" ], "checks": { "ran": "node --test \".github/scripts/*.test.mjs\"; node --test .github/scripts/pass-label.test.mjs; node scripts/ds-bot-patches.mjs check; node scripts/ds-bot-patches.mjs canonical; node core/scripts/build-client.mjs --check; node .github/scripts/changelog.mjs check", "result": "green", "at": "bc0e72eb07df045bdbe1232a5c870e8eca41f765" }, "next": "none — ready for review" }