Filed unassigned and ungraded by the domain:engine execution seat. ⛔ domain:*, priority and type are triage's.
This is #14587's Part 2, split off exactly on the condition its triage set (comment 5515035916):
Part 2 stays here as a stated open half rather than getting its own card, because I cannot anchor it until the es-ES/zh-CN difference is explained — a card whose fix site is unknown is not yet dispatchable. If the implementer establishes that it needs separate work, file it then, with the difference measured.
The implementer established it. The difference is measured, below. ⇒ the card is now anchorable.
⭐ The es-ES/zh-CN difference is provenance, not regeneration — and it reframes the class
The triage's working hypothesis was a locale-specific regeneration, or a hash that updated for one locale and not another. Neither happened, because the source never moved. packages/spec/src/ui/dashboard.form.ts:21 has carried 'Grid sizing and refresh cadence.' since the file was created, and that file has two commits.
What differs is where each locale's values came from — all on 2026-05-28:
| locale |
commit |
what it did |
| all three |
ae2da1e7d |
seeded every leaf with the English source verbatim |
| es-ES, ja-JP |
874cb084e "translate metadata-forms.* into ja-JP and es-ES" |
translated the seeded English — correct |
| zh-CN |
e0077ea36 "consolidate metadata-forms translations into generated bundle" |
deleted src/metadata-translations/zh-CN.ts (746 lines) and carried its values in — ⛔ never reconciled against the seeded English |
The exact stale string sits at metadata-translations/zh-CN.ts:470 in e0077ea36's parent.
⇒ ⭐ A mistranslation at authoring time, not a drift channel. That bounds the whole class: one import of an older hand vocabulary that was never checked against source. Not a recurring leak — a one-time reconciliation. es-ES and ja-JP are correct at both of #14587's leaves; zh-CN is alone.
The population, measured
Both bundles flattened to dotted leaf paths — 767 leaves each, key sets identical, zero unparsed lines — and every zh-CN leaf compared against its en counterpart (en is rewritten from source on every extract and never merged, so it is the source's copy):
| population |
count |
status |
byte-identical to en (untranslated fills) |
154 |
all carry a digest in zh-CN.source-hashes.generated.ts; findStaleFills reports 0 stale |
differ from en, carry no digest — LEGACY-TRUSTED |
613 |
⛔ every instrument in the repo is silent on these by construction |
All 613 were read. 26 assert something the source does not, or drop a distinct concept the source names — enumerated with source and zh-CN side by side in #14587 comment 5524387962, along with 18 looser paraphrases deliberately excluded from the count so the threshold is auditable rather than asserted.
Two are worth singling out, because the same bundle gets the same concept right elsewhere:
action.fields.body.helpText says the body is JavaScript. Its sibling hook.fields.body.helpText, translating the identical source sentence, correctly reads 「L1 表达式或 L2 沙箱 JS 体」.
dashboard.sections.basics.description promises an icon input. That section holds name, label and description — the dashboard form declares no icon field at all. A translation asserting a UI element that does not exist.
(One of the 26 lands in #14587's own PR; four more are in its completion round, bounded to the dashboard subtree. The remaining ~21 are this card's.)
⛔ The instrument is blind by construction, and its own header says so
scripts/check-i18n-stale-fill.mjs detects a leaf that is a byte copy of a previous source revision, via cross-locale agreement or a recorded digest. These leaves are neither. Its header already states the general case: once a leaf is not equal to the current source, a stale fill is indistinguishable by value from a real translation (2648 of 3010 leaves differ from en in at least one locale). ⇒ a hand-written mistranslation is a strictly harder case than the one that gate declined to attempt.
Measured by ablation, with every prerequisite cleared — reverting one string, then restoring with blob equality asserted:
ABLATED EXIT=0 :: pnpm check:i18n OK (9 package(s) — all bundles in sync)
ABLATED EXIT=0 :: pnpm check:i18n-stale-fill OK (10 bundle set(s) — no new stale fills, 0 baselined)
ABLATED EXIT=0 :: pnpm check:i18n-coverage OK (13 config(s), 691 baselined untranslated string(s), none new)
All three stayed green with the stale string in place. Predicted before running, then observed.
⚠️ Also measured, closing half of what the triage asked: check-i18n-stale-fill reports 27 provenance companions, 27 served, 0 unserved, so its UNSERVED_PROVENANCE half is already clean. And ja-JP — recorded as unmeasured by the triage — is correct at both leaves.
What this card is, and the ⛔ trap it must avoid
⇒ It is not "make the hash machinery report drift". The hash machinery correctly declines to claim anything about a translator-written string, and refreshing a digest to silence a report is what its own header forbids.
It is: the 613 legacy-trusted zh-CN leaves have never been compared against their source, and at least 26 are wrong. A one-time reconciliation pass is decidable by a reader; a gate for it is not, unless something records that a human compared each leaf against a specific source revision. Whether that is worth building is a maintainer call.
⛔ The trap: ⛔ do not write a second stale-detection instrument beside the one that exists. The triage named this — "a second vocabulary for 'this translation is stale' is the debt, not the fix."
No overlap — checked, not assumed
#14653, #14728 and #14749 all concern which strings enter the coverage population (extractor walk gaps, duplicate counting, inline I18nLabel maps). ⛔ None asks whether a string already in the bundle still means what its source means. (Incidentally the sweep reproduced #14728's figure exactly: 691 baselined units.)
Refs: #14587 (the instance and the full 26-leaf table at comment 5524387962) · PR #14926 · #14653 / #14728 / #14749 (adjacent, non-overlapping).
Filed unassigned and ungraded by the
domain:engineexecution seat. ⛔domain:*, priority and type are triage's.This is #14587's Part 2, split off exactly on the condition its triage set (comment 5515035916):
The implementer established it. The difference is measured, below. ⇒ the card is now anchorable.
⭐ The es-ES/zh-CN difference is provenance, not regeneration — and it reframes the class
The triage's working hypothesis was a locale-specific regeneration, or a hash that updated for one locale and not another. Neither happened, because the source never moved.
packages/spec/src/ui/dashboard.form.ts:21has carried'Grid sizing and refresh cadence.'since the file was created, and that file has two commits.What differs is where each locale's values came from — all on 2026-05-28:
ae2da1e7d874cb084e"translate metadata-forms.* into ja-JP and es-ES"e0077ea36"consolidate metadata-forms translations into generated bundle"src/metadata-translations/zh-CN.ts(746 lines) and carried its values in — ⛔ never reconciled against the seeded EnglishThe exact stale string sits at
metadata-translations/zh-CN.ts:470ine0077ea36's parent.⇒ ⭐ A mistranslation at authoring time, not a drift channel. That bounds the whole class: one import of an older hand vocabulary that was never checked against source. Not a recurring leak — a one-time reconciliation. es-ES and ja-JP are correct at both of #14587's leaves; zh-CN is alone.
The population, measured
Both bundles flattened to dotted leaf paths — 767 leaves each, key sets identical, zero unparsed lines — and every zh-CN leaf compared against its
encounterpart (enis rewritten from source on every extract and never merged, so it is the source's copy):en(untranslated fills)zh-CN.source-hashes.generated.ts;findStaleFillsreports 0 staleen, carry no digest — LEGACY-TRUSTEDAll 613 were read. 26 assert something the source does not, or drop a distinct concept the source names — enumerated with source and zh-CN side by side in #14587 comment 5524387962, along with 18 looser paraphrases deliberately excluded from the count so the threshold is auditable rather than asserted.
Two are worth singling out, because the same bundle gets the same concept right elsewhere:
action.fields.body.helpTextsays the body is JavaScript. Its siblinghook.fields.body.helpText, translating the identical source sentence, correctly reads 「L1 表达式或 L2 沙箱 JS 体」.dashboard.sections.basics.descriptionpromises an icon input. That section holdsname,labelanddescription— the dashboard form declares no icon field at all. A translation asserting a UI element that does not exist.(One of the 26 lands in #14587's own PR; four more are in its completion round, bounded to the
dashboardsubtree. The remaining ~21 are this card's.)⛔ The instrument is blind by construction, and its own header says so
scripts/check-i18n-stale-fill.mjsdetects a leaf that is a byte copy of a previous source revision, via cross-locale agreement or a recorded digest. These leaves are neither. Its header already states the general case: once a leaf is not equal to the current source, a stale fill is indistinguishable by value from a real translation (2648 of 3010 leaves differ fromenin at least one locale). ⇒ a hand-written mistranslation is a strictly harder case than the one that gate declined to attempt.Measured by ablation, with every prerequisite cleared — reverting one string, then restoring with blob equality asserted:
All three stayed green with the stale string in place. Predicted before running, then observed.
check-i18n-stale-fillreports 27 provenance companions, 27 served, 0 unserved, so itsUNSERVED_PROVENANCEhalf is already clean. And ja-JP — recorded as unmeasured by the triage — is correct at both leaves.What this card is, and the ⛔ trap it must avoid
⇒ It is not "make the hash machinery report drift". The hash machinery correctly declines to claim anything about a translator-written string, and refreshing a digest to silence a report is what its own header forbids.
It is: the 613 legacy-trusted zh-CN leaves have never been compared against their source, and at least 26 are wrong. A one-time reconciliation pass is decidable by a reader; a gate for it is not, unless something records that a human compared each leaf against a specific source revision. Whether that is worth building is a maintainer call.
⛔ The trap: ⛔ do not write a second stale-detection instrument beside the one that exists. The triage named this — "a second vocabulary for 'this translation is stale' is the debt, not the fix."
No overlap — checked, not assumed
#14653, #14728 and #14749 all concern which strings enter the coverage population (extractor walk gaps, duplicate counting, inline
I18nLabelmaps). ⛔ None asks whether a string already in the bundle still means what its source means. (Incidentally the sweep reproduced #14728's figure exactly: 691 baselined units.)Refs: #14587 (the instance and the full 26-leaf table at comment 5524387962) · PR #14926 · #14653 / #14728 / #14749 (adjacent, non-overlapping).