Uh oh!
There was an error while loading. Please reload this page.
fix(scripts): require --actor, the way --files is required - #125
Merged
Conversation
check-translation-ownership.mjs documented `--actor <login>` but defaulted it to the empty string and judged the PR anyway. An empty actor can never equal a non-empty bot login, so a translation-account PR invoked without the flag was rejected as hand-written: a confident verdict reached with the discriminator the check rests on absent. The argument is now required exactly while TRANSLATION_BOT_LOGIN is set, which is the only condition under which it is read. With the variable unset the check stays inert and a missing --actor still exits 0, unchanged. Declared second change, same species: a --files path that does not exist is answered with the usage message instead of a raw ENOENT stack. Every other read failure still keeps its stack. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Yaqu7kmKZM3tRPd9Y4xivo
…ation Rework of the first commit on this branch, which implemented the conditional form. The governing ruling on the card is the triage adjudication: `--actor` is required exactly the way `--files` is, one usage-error convention for the file. The actor is the discriminator the check is built on and the header documents it as part of the invocation, yet it defaulted to the empty string and the PR was judged anyway — an empty actor can never equal a non-empty bot login, so a translation-account PR invoked without the flag came back rejected as hand-written. Declared, therefore enforced. This answers a malformed invocation, not the meaning of the inert path: a well-formed call with TRANSLATION_BOT_LOGIN unset still reports and passes. Declared second change, unchanged from the first round: a --files path that does not exist is answered with the usage message instead of a raw ENOENT stack, narrowed to ENOENT so every other read failure keeps its stack. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Yaqu7kmKZM3tRPd9Y4xivo
os-elon
marked this pull request as ready for review
August 19, 2026 00:26
Uh oh!
There was an error while loading. Please reload this page.
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
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
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#116
What changed
check-translation-ownership.mjsdocumented--actor LOGINas part of its invocation butdefaulted the value to the empty string and judged the PR anyway. An empty actor can never
equal a non-empty
TRANSLATION_BOT_LOGIN, soisBotwas false and a translation-account PRinvoked without the flag was rejected as hand-written — a confident verdict reached with the
discriminator the whole check rests on absent, and nothing saying so.
--actoris now required unconditionally, exactly the way--filesis: sameUsageErrorclass from #117, same usage block, no stack, exit 1. Declared, therefore enforced — one usage
convention for the whole file.
This is the governing ruling on the card: the triage adjudication (option 1), issue comment
5331667901. It answers a malformed invocation and nothing else. What the check means for
a well-formed call while
TRANSLATION_BOT_LOGINis unset — the inert report-and-pass path — isthe subject of #68 and is not addressed here; rows 01-03 and 09-14 of the matrix below pin it
byte for byte.
The transcript below is verbatim except for one thing: GitHub strips an angle bracket followed
by a letter from stored bodies (measured on an earlier revision of this description, which lost
every placeholder inside this very code fence), so each placeholder here carries a space the
script does not print.
Argument validation runs before the list file is read, so a call that is wrong in two ways
reports the missing
--actorrather than the unreadable path.Declared second change: the unguarded
ENOENTAuthorised on dispatch as a rider, same species and named in the card's tail: a
--filespaththat does not exist died with a raw seven-line
ENOENTstack, which reads as "this script isbroken" rather than "I called it wrong". It is now the same usage failure as omitting
--files.The catch is narrowed to
error.code === 'ENOENT'— every other way the read can fail (adirectory, a permission error) still rethrows and keeps its stack — and the
UsageErrordoccomment was corrected to match, since it previously promised a stack for "an unreadable list
file", which now means a file that exists but cannot be read.
Invocation matrix, before and after
25 invocation shapes recorded against
69204aband against this branch, then compared block byblock (env spelling, argv, exit status, stdout, stderr). 13 byte-identical, 12 changed — and
every changed row is either the defect, the intended requirement, or the rider.
Unchanged — the invariant set, including every shape the real caller produces:
transbottransbottransbottransbottransbottransbot--actor=…--files=…equals formtransbot--filesat alltransbot--files(thetranslations.ymlshape)Intended change — a missing or empty actor is now a usage failure everywhere:
--actor, clean / artifacts--actor, artifacts--actor, cleantransbot--actor, artifactstransbot--actor, cleantransbot--actor, cleantransbot--actor, artifactsRider:
transbot--filesnonexistenttransbot--actorand nonexistent--filesRows 04-08 are the behaviour change the ruling asks for: an invocation that omits the
documented discriminator now says so instead of returning a verdict. The one thing that had to
survive did: the only real caller,
.github/workflows/translations.yml:48, always passes--actor, and every shape it produces (rows 09-14, plus row 25 for its relative--filespath) is byte-identical before and after. Rows 07-08 also record that
TRANSLATION_BOT_LOGINset to the empty string or to whitespace still behaves as unset, unchanged by this PR.
Gates
All on Node 22.22.2, matching CI, at commit
1778d4a:pnpm install --frozen-lockfile— 0pnpm turbo run type-check --continue --force— 0pnpm turbo run build --force— 0pnpm turbo run test --force— 0 (includes the self-test runner)node .github/scripts/check-translations.mjs— 0node .github/scripts/check-translation-output.mjs --self-test— 0node .github/scripts/check-translation-output.mjs --fileson this PR's changed list — 0--files, actor passed) — 0No changeset: this repo does not use them.
Generated by Claude Code