Commit 8450eea
feat(gate): detect translation leaves stranded on a previous source revision (#12067)
* feat(gate): detect translation leaves stranded on a previous source revision
`os i18n extract --fill=default` fills gaps only, so the ordinary sequence —
extract, revise the source string, extract again — rewrites `en` (never merged,
#8543) and silently keeps the previous source text in every translated locale.
The bundle stays in sync BY KEY, so `check:i18n` reports OK, and the leaf is
still present, so `check:i18n-coverage` counts it translated: it tests presence,
not freshness. Measured on PR #11659 at bbe0b17 — three locales serving a
602-char superseded draft of a 411-char help string under 31 green checks.
"Flag untranslated leaves that no longer match the current source" cannot be
implemented as stated: "untranslated" has exactly one observable spelling today,
EQUAL to the current source, so the two predicates are complementary rather than
conjoinable. Measured on this tree, 2648 of 3010 leaves differ from `en` — that
set is essentially every correct translation in the repo.
What IS decidable without provenance is cross-locale agreement: two different
target languages do not independently produce byte-identical prose, so when they
hold the same bytes neither translated it — both were filled from the source, and
if those bytes are not the CURRENT source they are a previous revision of it.
Three further conditions each close one measured false-positive class (47 -> 11
-> 5); none of them is a threshold.
Existing drift is frozen with a reason per entry, all five of it real and
pre-existing; NEW drift fails. Repairing those bundles is deliberately not this
change — #11671 was re-routed to the tooling lane for that reason.
Needs no workspace build (it reads the committed bundles as text), so it runs in
`Lint & Repo Gates` rather than with its two i18n siblings in `typecheck`.
Part of #11671
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
* fix(gate): put check-i18n-stale-fill's dispatch behind isEntrypoint
The module exports its rules so they can be imported; without the guard that
import runs the whole gate inside the importer and exits its process — the
silent-success direction scripts/invoked-as.mjs documents. check:entry-guard
caught it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
* chore(pm): record check:i18n-stale-fill's bare-root verdict as REFUSE-UNSPELLABLE
The new gate reaches its population through the same findExtractConfigs walk
check:i18n and check:i18n-coverage use, so it joins them rather than being
judged apart: the walk recurses across the root, but what it ADMITS is a
filename-and-segment test — 9 of 5185 tracked files (0.17%).
Measured rather than inherited: both star spellings of the real population
collapse to the same malformed double-separator prefix, and hintCovers matched
it against NOTHING when checked against a real config path; the only spellings
that cover anything collapse to the bare root. So a declaration is either a live
hint over zero files or a hint over 5185 files to reach 9 — and declaring a root
the gate does not read wholesale is the costlier error.
Only the TRIAGE map moves. The recogniser, the sweep and the self-test are
untouched.
Part of #11671
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 40225e9 commit 8450eea
6 files changed
Lines changed: 541 additions & 1 deletion
File tree
- .github/workflows
- scripts
- pm
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1388 | 1388 | | |
1389 | 1389 | | |
1390 | 1390 | | |
| 1391 | + | |
| 1392 | + | |
| 1393 | + | |
| 1394 | + | |
| 1395 | + | |
| 1396 | + | |
| 1397 | + | |
| 1398 | + | |
| 1399 | + | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
1391 | 1404 | | |
1392 | 1405 | | |
1393 | 1406 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
0 commit comments