Add the project draft-quality gate to the enriched-draft arm after the source-echo erratum

This commit is contained in:
Claude (backend session) 2026-08-16 03:13:32 +03:00
parent a5f0e0ce37
commit b6bcefc199

View file

@ -159,6 +159,71 @@ def free_text(p: str, arm: str, uid: str) -> str:
raise SystemExit(f"{arm} не бесплатный арм")
# ── ЭХО-ГЕЙТ ОБОГАЩЁННОГО ЧЕРНОВИКА ───────────────────────────────────────────────────────────
# ⚠⚠ ЭРРАТА Э-17.1, ОБЪЯВЛЕНА ПОСЛЕ 10 КУПЛЕННЫХ КЛЕТОК И ДО ОСТАЛЬНЫХ ПОКУПОК. Первые китайские
# клетки `Z8` показали **3 эха из 10**: модель вернула ИСХОДНИК с косметически переставленными
# репликами вместо перевода (валидный HTTP 200, `finish=stop`, доля хань ~0.99).
#
# Это не случайность и не новость — это ДОКУМЕНТИРОВАННЫЙ класс, и я обязан был проверить его
# ДО покупки, а не после:
# · черновая роль ходит на `deepseek-v4-flash` с `reasoning_effort:"low"`, а квирк-бюллетень
# (`00-provider-quirks.md`, п.4) прямо говорит: «`effort:"low"` ПЕРЕ-ВООРУЖАЕТ эхо-мину»,
# защита деградирует НЕПРЕРЫВНО с эффортом, а не скачком на «выключено»;
# · запрет D21.6 там же: **не вносить языковые констрейнты в промты reasoning-ослабленных путей
# без per-model замера** — на grok одна формулировка констрейнта подняла эхо 3/10 → 9/10.
# Мандат перевёрстки — ровно такой констрейнт: он ОПИСЫВАЕТ синтаксис исходного языка.
#
# ⇒ Это не помеха замеру, а ЕГО ПЕРВЫЙ РЕЗУЛЬТАТ: обогащение промта черновика имеет цену, и цена
# эта — частота тихого отказа на дешёвой модели. Число печатается как результат арма, а не
# прячется. Обработка — штатная для проекта: гейт годности + ОДИН ре-ген (квирк-бюллетень п.6:
# эхо стохастично по вызову, ре-ген на flash в 7.6× дешевле эскалации). Клетки с эхом уходят в
# карантин под именем, которое глоб кассы по-прежнему видит: деньги за них списаны и обязаны
# остаться видимыми.
REGEN_MAX = 1
def quarantine(tg: str, why: str) -> None:
f = OUT / f"{tg}.json"
if not f.exists():
return
n = 1
while (OUT / f"{tg}.ЭХО{n}.json").exists():
n += 1
f.rename(OUT / f"{tg}.ЭХО{n}.json")
print(f" {tg}: {why} → карантин .ЭХО{n}.json (деньги остаются видимы кассе)")
def draft_ok(p: str, uid: str) -> str:
"""Обогащённый черновик, ПРОШЕДШИЙ штатный гейт годности проекта. Пусто = негоден.
Через эту функцию, а не через `cell`, обязан ходить КАЖДЫЙ потребитель `Z8`: эхо-клетка
имеет `finish=stop` и непустое содержимое, поэтому обычная проверка её пропускает и боевой
редактор `Z8R` принялся бы «редактировать» китайский текст за полную цену.
"""
t = cell(tag(p, "Z8", uid))
return "" if (not t.strip() or C.draft_defect(t)) else t
def echo_report() -> None:
for p in PAIRS:
_pair(p)["wire"]()
us = chosen(p)
bad, good, quar = [], 0, 0
for u in us:
t = cell(tag(p, "Z8", u["uid"]))
quar += len(list(OUT.glob(f"{tag(p, 'Z8', u['uid'])}.ЭХО*.json")))
if not t.strip():
continue
why = C.draft_defect(t)
bad.append((u["uid"], why)) if why else None
good += not why
n = good + len(bad)
print(f"{p}: годных {good} · с дефектом {len(bad)} из {n} "
f"({len(bad) / max(n, 1):.0%}) · в карантине {quar}")
for uid, why in bad[:5]:
print(f" {uid}: {why}")
def crit_raw(p: str, uid: str) -> str:
"""Ответ смыслового критика этой единицы — КУПЛЕН прошлой осью, здесь $0."""
return cell(C.tag(_pair(p)["crit"], uid, "crit"))
@ -298,12 +363,22 @@ def buy(p: str, which: list[str]) -> None:
if cell(tg).strip():
continue
if arm == "Z8":
_buy(led, tg, DRAFT_MODEL, z8_msgs(p, src), mo,
role="translator", uid=uid, arm=arm)
# штатный гейт годности + ОДИН ре-ген: эхо стохастично по вызову (квирки п.6)
for attempt in range(REGEN_MAX + 1):
_buy(led, tg, DRAFT_MODEL, z8_msgs(p, src), mo,
role="translator", uid=uid, arm=arm, attempt=attempt)
why = C.draft_defect(cell(tg))
if not why:
break
if attempt < REGEN_MAX:
quarantine(tg, f"черновик негоден ({why}), ре-ген")
else:
print(f" {uid}: {arm} негоден и после ре-гена ({why}) — "
"клетка остаётся, арм на этой единице объявляется несобранным")
elif arm == "Z8R":
d = cell(tag(p, "Z8", uid))
d = draft_ok(p, uid)
if not d.strip():
print(f" {uid}: обогащённого черновика нет — {arm} пропущен")
print(f" {uid}: годного обогащённого черновика нет — {arm} пропущен")
continue
_buy(led, tg, EDITOR, editor_msgs(p, src, d), mo,
role="editor", uid=uid, arm=arm)
@ -395,6 +470,12 @@ def cmd_selftest() -> int:
and DISCOURSE_HEAD in z8, f"дельта {len(z8) - len(base)} знаков")
ck(f"{p}: в Z8 нет нераскрытых плейсхолдеров", "{{" not in z8)
ck(f"{p}: FEWSHOT в Z8 не уехал (в бою его нет ни у кого)", "FEWSHOT" not in z8)
# ⚠ Э-17.1: потребитель Z8 обязан ходить через гейт годности, иначе редактор будет
# «редактировать» эхо исходника за полную цену. Гейт проверяется НА ЭХЕ, а не на словах.
ck(f"{p}: гейт годности ловит эхо исходника",
bool(C.draft_defect(u["source"] * 3)), "штатный гейт проекта молчит на исходнике")
ck(f"{p}: гейт годности пропускает нормальный русский текст",
not C.draft_defect(free_text(p, "ZD", u["uid"])))
# Z1 обязан быть БОЕВЫМ редактором плюс замечания, а не новым промтом
notes, _ = critic_notes(p, u["uid"])
z1 = z1_msgs(p, u["source"], free_text(p, "ZD", u["uid"]), notes or ["тест"])
@ -456,6 +537,8 @@ if __name__ == "__main__":
cmd_dry()
elif a[0] == "--plan":
cmd_plan()
elif a[0] == "--echo":
echo_report()
elif a[0] == "--buy":
pr = [x for x in a[1:] if x in PAIRS] or list(PAIRS)
ar = [x for x in a[1:] if x in ARMS] or list(ARMS)