Found during the landing sweep that merged #630, while checking #628's premise. Filed rather than folded, per AGENTS.md — and filed although it contradicts a PR this sweep had just merged, which is the case AGENTS.md calls out explicitly.
The finding
#630 (513145a1, "escape the bidi controls in the QML i18n tests", fixes #610 and #591) escaped one half of src/qt/forms/tests/tst_i18n.qml and left the other half raw. The raw survivors are in the code that PR added for #591.
Verification status: reproduced on master @ 513145a1
Five lines carry raw U+200E / U+200F bytes:
$ grep -nP '[\x{202A}-\x{202E}\x{2066}-\x{2069}\x{200E}\x{200F}]' src/qt/forms/tests/tst_i18n.qml | cat -A
284: compare(Qt.locale("az_IR").positiveSign, "M-bM-^@M-^N+M-bM-^@M-^N")
309: compare(localeForm.normalizeLocaleNumber("M-bM-^@M-^N+5", ".", "", "-", "M-bM-^@M-^N+"), "5") // ar_DZ
310: compare(localeForm.normalizeLocaleNumber("M-bM-^@M-^N+M-bM-^@M-^N5", ".", "", "-", "M-bM-^@M-^N+M-bM-^@M-^N"), "5") // az_IR
311: compare(localeForm.normalizeLocaleNumber("M-bM-^@M-^O+5", ".", "", "-", "M-bM-^@M-^O+"), "5") // ckb_IQ
318: compare(localeForm.normalizeLocaleNumber("M-bM-^@M-^N+M-bM-^@M-^N5", ".", ""), null)
$ grep -cP '…' src/qt/forms/tests/tst_i18n.qml
5
M-bM-^@M-^N is E2 80 8E = U+200E LEFT-TO-RIGHT MARK; M-bM-^@M-^O is E2 80 8F = U+200F RIGHT-TO-LEFT MARK.
The same file uses the escaped form 13 times, so this is an inconsistency inside one file rather than a convention nobody adopted:
$ grep -c '\\u200' src/qt/forms/tests/tst_i18n.qml
13
226: compare(signForm.normalizeLocaleNumber("−5", ".", "", "−"), "-5") // fa_IR
227: compare(signForm.normalizeLocaleNumber("-5", ".", "", "-"), "-5") // az_IR
228: compare(signForm.normalizeLocaleNumber("-5", ".", "", "-"), "-5") // ar_DZ
Lines 226–234 are the negative-sign block — #610's original subject, escaped exactly as asked. Lines 284–318 are the positive-sign block — #591's addition, raw. Both landed in the same commit.
What I did not verify: whether the five raw spellings are deliberate — e.g. a case meant to prove the parser handles a raw literal. I read the surrounding comments (lines 276–286, 314–320) and found no statement to that effect; they explain why a bidi-prefixed sign is two or three UTF-16 units, not why these five are written raw while their thirteen neighbours are escaped. If a reason exists, it was not written down, which is itself worth fixing given that #610's whole argument was that an invisible character in a source file is a maintenance hazard.
Why it matters beyond tidiness
#610's case was that a reviewer cannot see these characters, so a wrong one survives review. That is precisely what happened here: the PR closing #610 introduced five more, and the review — mine included — did not catch it, because the diff renders them invisibly.
#628 already argues that no lint keeps raw bidi controls out of first-party sources and notes "the authoring path that introduces them was hit twice while fixing #610". This is the third time, in the merged result. This issue is evidence for #628, not a substitute for it: fixing these five lines without the lint leaves the next occurrence to be found by whoever next greps for it.
What would change the verdict
Related
🤖 Generated with Claude Code
https://claude.ai/code/session_01VptDWG2fKr2vBnLSJcgzgW
Found during the landing sweep that merged #630, while checking #628's premise. Filed rather than folded, per AGENTS.md — and filed although it contradicts a PR this sweep had just merged, which is the case AGENTS.md calls out explicitly.
The finding
#630 (
513145a1, "escape the bidi controls in the QML i18n tests", fixes #610 and #591) escaped one half ofsrc/qt/forms/tests/tst_i18n.qmland left the other half raw. The raw survivors are in the code that PR added for #591.Verification status: reproduced on
master@513145a1Five lines carry raw U+200E / U+200F bytes:
M-bM-^@M-^NisE2 80 8E= U+200E LEFT-TO-RIGHT MARK;M-bM-^@M-^OisE2 80 8F= U+200F RIGHT-TO-LEFT MARK.The same file uses the escaped form 13 times, so this is an inconsistency inside one file rather than a convention nobody adopted:
Lines 226–234 are the negative-sign block — #610's original subject, escaped exactly as asked. Lines 284–318 are the positive-sign block — #591's addition, raw. Both landed in the same commit.
What I did not verify: whether the five raw spellings are deliberate — e.g. a case meant to prove the parser handles a raw literal. I read the surrounding comments (lines 276–286, 314–320) and found no statement to that effect; they explain why a bidi-prefixed sign is two or three UTF-16 units, not why these five are written raw while their thirteen neighbours are escaped. If a reason exists, it was not written down, which is itself worth fixing given that #610's whole argument was that an invisible character in a source file is a maintenance hazard.
Why it matters beyond tidiness
#610's case was that a reviewer cannot see these characters, so a wrong one survives review. That is precisely what happened here: the PR closing #610 introduced five more, and the review — mine included — did not catch it, because the diff renders them invisibly.
#628 already argues that no lint keeps raw bidi controls out of first-party sources and notes "the authoring path that introduces them was hit twice while fixing #610". This is the third time, in the merged result. This issue is evidence for #628, not a substitute for it: fixing these five lines without the lint leaves the next occurrence to be found by whoever next greps for it.
What would change the verdict
invalidif the five raw spellings turn out to be deliberate and a comment saying so is added — the requirement is that the reason be written down, not that the bytes change.Related
🤖 Generated with Claude Code
https://claude.ai/code/session_01VptDWG2fKr2vBnLSJcgzgW