Commit 9c1bcda
tooling(i18n): gate that every declared translation group is walked by the extractor (#14763)
* tooling(i18n): gate that every declared translation group is walked by the extractor
A translation key family lands in `packages/spec` with a resolver that reads
it, and the CLI extractor that produces the coverage population is updated
later or not at all. In between, `os i18n extract` scaffolds no key for the
family, so no translator is asked for one, so `check:i18n-coverage` measures a
debt of zero and reports OK while the strings ship in English. Five instances
so far, every one found by a person noticing rather than by an instrument.
`scripts/check-i18n-walk-parity.mjs` is the instrument. It reads the DECLARED
side off the built `TranslationDataSchema`'s zod shape (the contract, not the
source text) and the WALKED side off `collectExpectedEntries` run over a
fixture stack config that authors a member of every group, then asserts
`declared \ (walked u ledger) = {}` and that no ledger entry is stale.
The exemption ledger ships EMPTY and is shrink-only in the `KNOWN_IMPORT_UNSAFE`
shape: every entry carries the reason the group has no extractor face, a blank
or pro-forma reason fails, a stale entry names itself, and `LEDGER_CEILING`
refuses growth the author did not edit into the same diff.
Deliberately NOT a derivation of the extractor from the resolvers: the two
enumerations answer different questions over different inputs. The unit is the
top-level group, the one name both sides can spell.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
* tooling(i18n): mark the exemption-ledger remedy MAINTAINER-ONLY
`check:ratchet-remedy-authority` reached the new gate and was right (#8435): its
unwalked-group message offered two remedies and one of them EXPANDS a
shrink-only registry, which is the author excusing themselves from the check
they just failed. Emitting the group in the extractor stays the landing author's
remedy and is offered first; adding an exemption is now named with its owner.
Registers the gate in that gate's hand-classified control corpus as `marked`,
the same reading as check-auth-mount-ledger.mjs and check-exported-any-returns.mts:
there IS a legitimate act here — a group keyed by strings no stack config
declares genuinely has no extractor face — so refusal would be untrue.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
* tooling(i18n): ledger the three unwalked translation groups by maintainer ruling
The walk-parity gate's own first red named three declared translation groups
with no extractor face: `messages`, `settingsCommon` and `settings`. The
maintainer ruled (2026-09-04, #14653 comment 5535827386) that all three enter
the gate's exemption ledger in this PR, each with its reason, and that no
`settings` emitter is built now.
That act is ⛔ MAINTAINER-ONLY by the gate's own failure text, so it is taken
under that ruling and nowhere else:
messages keyed by arbitrary ids composed at the `i18n.t()` call sites;
no registry or stack config enumerates the id set.
settingsCommon the Settings UI's own five source-badge labels — the console's
words in every app, ruled out of per-app bundles on #7646.
settings keyed by `SettingsManifest.namespace`, which is platform code
rather than authored metadata. A DEFERRAL, not a fact: the
terminal state is held on #15178.
`LEDGER_CEILING` moves 0 -> 3 in the same diff, which is the mechanism working
as designed. No check is weakened: the reason floor, the placeholder refusal,
the both-direction size ratchet, the stale-entry detection, the empty-population
refusal and the MAINTAINER-ONLY remedy text are all untouched.
The self-test's `ledger is empty` pin is replaced by three that stay true and
still bite — the ledger's key set equals the recorded unwalked set, every
reason survives the gate's own reason checks, and its size is exactly the
ceiling under the real ratchet classifier, so an entry without a ceiling bump
(or a ceiling bump without an entry) reddens in the self-test as well as in
production.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WXyGTWPbbreqXow7Z2pZCk
---------
Co-authored-by: claude[bot] <claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>1 parent 5f5511f commit 9c1bcda
5 files changed
Lines changed: 832 additions & 0 deletions
File tree
- .github/workflows
- scripts
- fixtures/i18n-walk-parity
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5344 | 5344 | | |
5345 | 5345 | | |
5346 | 5346 | | |
| 5347 | + | |
| 5348 | + | |
| 5349 | + | |
| 5350 | + | |
| 5351 | + | |
| 5352 | + | |
| 5353 | + | |
| 5354 | + | |
| 5355 | + | |
| 5356 | + | |
| 5357 | + | |
| 5358 | + | |
| 5359 | + | |
| 5360 | + | |
| 5361 | + | |
| 5362 | + | |
| 5363 | + | |
| 5364 | + | |
| 5365 | + | |
| 5366 | + | |
| 5367 | + | |
5347 | 5368 | | |
5348 | 5369 | | |
5349 | 5370 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
| |||
0 commit comments