R-325 (controller half): retrieval_promise_gate imports the shared stem list

STEMS now comes from felhom.eu/scripts/customer_copy_vocab.py (RETRIEVAL_STEMS), read the
way controller_gates.py reads the other shared checkers (CI clones felhom.eu beside this repo);
an absent or empty vocabulary is INCONCLUSIVE (exit 2), never a pass. Decoys: vocabulary
absent -> rc 2; an invented stem in a doctored shared list convicts a template using it.
hub_copy_gate.check_drift on this file now reads 'ok — single source'.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-05 22:23:40 +02:00
parent 8ce496f124
commit daeed27223
2 changed files with 67 additions and 2 deletions
+18 -1
View File
@@ -51,7 +51,24 @@ GO_SOURCES = [
# R-311 adds `visszanyit`: the honest new message says a customer needs support's help „a régebbi
# előzményed visszanyitásához". That is the SAME claim in a fourth verb, and the docstring above
# records what happens when the guard chases words instead of claims — it misses the next one.
STEMS = ["visszaállíthat", "visszaszerezhet", "visszahozhat", "visszanyit"]
#
# R-325: the list is NOT kept here. It lives ONCE in felhom.eu/scripts/customer_copy_vocab.py, which
# the hub's copy gate imports too — two copies of a word list is the R-299 defect exactly. The
# sibling clone is read the way controller_gates.py reads reuse_refs_check.py: CI clones felhom.eu
# beside this repo, and an ABSENT clone is INCONCLUSIVE (exit 2) — never a pass on an empty list.
# FELHOM_SHARED_SCRIPTS overrides the directory (the decoy suite uses it; nothing else should).
_SHARED_SCRIPTS = os.environ.get("FELHOM_SHARED_SCRIPTS") or os.path.normpath(
os.path.join(_HERE, "..", "..", "..", "felhom.eu", "scripts"))
if not os.path.isfile(os.path.join(_SHARED_SCRIPTS, "customer_copy_vocab.py")):
print("retrieval-promise gate INCONCLUSIVE: the shared vocabulary is missing (%s) — the felhom.eu "
"clone must sit beside this repo; without the stems nothing can be judged" %
os.path.join(_SHARED_SCRIPTS, "customer_copy_vocab.py"))
sys.exit(2)
sys.path.insert(0, _SHARED_SCRIPTS)
from customer_copy_vocab import RETRIEVAL_STEMS as STEMS # noqa: E402
if not STEMS:
print("retrieval-promise gate INCONCLUSIVE: customer_copy_vocab.RETRIEVAL_STEMS is empty")
sys.exit(2)
# R-564 — THE SPLIT VERB. Hungarian moves the particle after the verb when something is stressed:
# „csak akkor ÁLLÍTHATÓK VISSZA", „csak a hiányzó fájlokat HOZOD VISSZA". The joined stems above never
+49 -1
View File
@@ -39,7 +39,8 @@ COVERS = {
"app-row-dedup": "hand-rolled row markup in partials/, AND a commented-out partial call",
"template-id": "a JS reference to a missing id, in partials/",
"secret-markup": "a secret templated into markup, in partials/",
"retrieval-promise": "an unregistered retrieval promise, in partials/",
"retrieval-promise": "an unregistered retrieval promise, in partials/; R-325: the shared vocabulary "
"absent (INCONCLUSIVE) and an invented stem in it convicting",
"mojibake": "CONTROL: already walked; proves the planted file is really reachable",
"debug-routes": "a live dispatcher case commented out - the button survives, the handler dies",
"golden-notice": "R-410 in the other direction: an empty dir must not count as a bake",
@@ -276,6 +277,53 @@ swapped("go-parity/nested-arg-ok", "i18n_go_parity.py", UPDATE_GO,
_one(_R576, 'util.MsgError("update.refusal.already", fmt.Sprintf("%s,%s", f(a, b), c)), "lost the race'),
expect="accept")
# --- retrieval-promise, R-325: the stems are IMPORTED from felhom.eu/scripts/customer_copy_vocab.py. ---
# Two shapes. (1) The vocabulary absent must be INCONCLUSIVE, never a pass on an empty list.
# (2) declaration-for-reachability: a gate that still carried a private literal would ignore the
# shared file. A doctored vocabulary with one invented stem, and a template using only that stem,
# must convict — proof the shared list is the one in force.
import shutil # noqa: E402
import tempfile # noqa: E402
def _retrieval_with_vocab(vocab_src):
d = tempfile.mkdtemp(prefix="r325-")
try:
if vocab_src is not None:
io.open(os.path.join(d, "customer_copy_vocab.py"), "w", encoding="utf-8").write(vocab_src)
env = dict(os.environ, FELHOM_SHARED_SCRIPTS=d)
p = subprocess.run([sys.executable, os.path.join("scripts", "retrieval_promise_gate.py")],
cwd=CTRL, env=env, capture_output=True, text=True)
return p.returncode, p.stdout + p.stderr
finally:
shutil.rmtree(d, ignore_errors=True)
ran += 1
_rc, _out = _retrieval_with_vocab(None)
if _rc != 2 or "INCONCLUSIVE" not in _out:
fails.append("retrieval-promise/vocab-absent: want rc=2 INCONCLUSIVE, got rc=%d\n%s" % (_rc, _out[-300:]))
else:
print(" ok %-20s %s" % ("retrieval-promise/vocab-absent", "stays undetermined"))
ran += 1
_made = not os.path.isdir(SUB)
if _made:
os.makedirs(SUB)
_planted = os.path.join(SUB, "decoy-r325.html")
io.open(_planted, "w", encoding="utf-8").write(u"<p>Minden adatod felhomdecoyszohato marad.</p>\n")
try:
_rc, _out = _retrieval_with_vocab(u'RETRIEVAL_STEMS = ["visszaállíthat", "felhomdecoyszo"]\n')
finally:
os.remove(_planted)
if _made and os.path.isdir(SUB) and not os.listdir(SUB):
os.rmdir(SUB)
if _rc != 1 or "felhomdecoyszo" not in _out:
fails.append("retrieval-promise/vocab-is-live: an invented stem in the SHARED list did not convict — the "
"gate is not reading customer_copy_vocab.py (rc=%d)\n%s" % (_rc, _out[-300:]))
else:
print(" ok %-20s %s" % ("retrieval-promise/vocab-is-live", "decoy rejected"))
# --- golden-notice: R-410's decoy, in the other direction. It is ADVISORY, so rc is never the ---
# --- question — what it COUNTED is. ---
ran += 1