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:
@@ -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
|
||||
|
||||
@@ -163,6 +163,13 @@ swapped("native-confirm/bundle", "native_confirm_gate.py", EN_JSON,
|
||||
_one('"launcher.masolva": "Copied"', '"launcher.masolva": "Copied\u0027+confirm(\u0027x\u0027)+\u0027"'))
|
||||
swapped("retrieval-promise/bundle", "retrieval_promise_gate.py", HU_JSON,
|
||||
_one('"launcher.link_masolasa": "Link másolása"', '"launcher.link_masolasa": "A mentésed bármikor visszaállítható."'))
|
||||
# Slice 1 (R-556): an English retrieval PROMISE is judged like a Hungarian one — and the same place
|
||||
# carrying a sentence that promises nothing is accepted (the gate registers claims, not words).
|
||||
swapped("retrieval-promise/en", "retrieval_promise_gate.py", EN_JSON,
|
||||
_one('"launcher.link_masolasa": "Copy link"', '"launcher.link_masolasa": "Your old backups can be restored at any time."'))
|
||||
swapped("retrieval-promise/en-ok", "retrieval_promise_gate.py", EN_JSON,
|
||||
_one('"launcher.link_masolasa": "Copy link"', '"launcher.link_masolasa": "Your old backups are listed on the restore page."'),
|
||||
expect="accept")
|
||||
swapped("secret-markup/bundle", "secret_in_markup_gate.py", EN_JSON,
|
||||
_one('"launcher.link_masolasa": "Copy link"', '"launcher.link_masolasa": "Copy {{.RetrievalPassword}}"'))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user