i18n slice 1 (A.2-A.4, A.6): narrowed English mask, marker coverage test, English retrieval stems, parse timing

Five v0.247.0 fixtures re-captured from UNCONVERTED v0.246.0 (89dd3e94) because their
one-word Hungarian data values had to become multi-word; two new cases (backups_tier_due,
app_info_installable) captured the same way — the coverage test found both gaps.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-17 17:15:23 +02:00
parent cc2ad41516
commit 1af89a54af
11 changed files with 1471 additions and 25 deletions
+49 -2
View File
@@ -96,6 +96,30 @@ ALLOWLIST = {
"there: the package the hub holds right now is the one about to be pinned. Left alone.",
}
# ── ENGLISH (localisation slice 1, R-556) ─────────────────────────────────────────────────────────
# The same claim, in the English bundle. Until slice 1 this gate read the Hungarian expansion only, so
# an English promise was unscanned — measured: a planted 'Your old backups can be restored at any
# time.' in en.json passed. English has no single stem; these are the phrasings of "it can be got
# back". Plain nouns and imperatives (Restore, Restoring..., Restore checked) are NOT claims and
# are deliberately not matched. Scanned in the ENGLISH expansion of every template.
EN_PATTERNS = [
r"\brestorable\b", r"\bcan (?:still )?be restored\b", r"\bcan (?:still )?restore\b",
r"\b(?:get|bring|getting|bringing) (?:them |it |these |those |your \w+ )?back\b",
r"\brecoverable\b", r"\bcan (?:still )?be recovered\b", r"\bcan (?:still )?recover\b",
r"\bretrievable\b", r"\bcan (?:still )?(?:be )?retrieved?\b", r"\breopen",
]
EN_RE = re.compile("|".join(EN_PATTERNS), re.I)
# English registrations — each mirrors a Hungarian entry above and carries its reason by reference.
ALLOWLIST_EN = {
("backups.html", "that can bring back the entire device"):
"= backups.html 'amelyből az egész készülék visszaállítható': the LOCAL whole-device backup.",
("layout.html", "Until then you can still get them back with your recovery code."):
"= layout.html 'Addig még visszaszerezheted őket...': R-302's TRUE branch.",
("layout.html", "whether your recovery code can still get them back"):
"= layout.html 'Hogy ezek még visszaszerezhetők-e': the cautious QUESTION branch.",
}
TEMPLATE_COMMENT = re.compile(r"\{\{/\*.*?\*/\}\}", re.S)
GO_COMMENT = re.compile(r"//[^\n]*|/\*.*?\*/", re.S)
@@ -148,12 +172,35 @@ def scan():
else:
ctx = text[max(0, m.start() - 100): m.end() + 100]
convictions.append((name, line, m.group(0), " ".join(ctx.split())[:160]))
# English: every template's English expansion, the same span-based registration.
for name, path, stripper in sources:
if not path.endswith(".html"):
continue
text = stripper.sub("", i18n_bundle.expand(open(path, encoding="utf-8").read(), "en"))
# Template actions carry English FIELD names (.Restorable) — code, not copy. Blanked, keeping
# line numbers.
text = re.sub(r"\{\{.*?\}\}", lambda m: re.sub(r"[^\n]", " ", m.group(0)), text, flags=re.S)
for m in EN_RE.finditer(text):
line = text[: m.start()].count("\n") + 1
hit = None
for k in (k for k in ALLOWLIST_EN if k[0] == name):
for om in re.finditer(re.escape(k[1]), text):
if om.start() <= m.start() and m.end() <= om.end():
hit = k
break
if hit:
break
if hit:
seen_keys.add(("en",) + hit)
else:
ctx = text[max(0, m.start() - 100): m.end() + 100]
convictions.append((name + " [en]", line, m.group(0), " ".join(ctx.split())[:160]))
return files, convictions, seen_keys
def main():
files, convictions, seen = scan()
stale = [k for k in ALLOWLIST if k not in seen]
stale = [k for k in ALLOWLIST if k not in seen] + [k for k in ALLOWLIST_EN if ("en",) + k not in seen]
for name, line, word, ctx in convictions:
print(f" {name}:{line} unregistered retrieval claim ({word}):\n …{ctx}…")
for k in stale:
@@ -166,7 +213,7 @@ def main():
print("knowability, or an unrelated local-backup sentence, add it to ALLOWLIST with the reason.")
return 1
print(f"retrieval-promise gate OK — {len(files)} surface(s) incl. {len(GO_SOURCES)} Go handler file(s), "
f"{len(ALLOWLIST)} registered claim(s), none unregistered")
f"{len(ALLOWLIST)} registered claim(s) + {len(ALLOWLIST_EN)} English, none unregistered")
print(" (BLIND SPOT: it registers WHERE the claim is made, not whether each conditional is wired")
print(" to a true predicate — that is what the R-302 render tests are for.)")
return 0