Raise the pack ceiling to 6.15 on the owner's sanction, funding the A1B re-buy that a session defect made necessary
This commit is contained in:
parent
6faa52f753
commit
2fed3d060f
2 changed files with 71 additions and 24 deletions
|
|
@ -165,45 +165,71 @@ def canon_gaps(src: str, out: str) -> list[str]:
|
|||
# «батарея + канон-гейт»; (2) значения проверок — СЛОВАРИ, и наивный фильтр, будь он даже
|
||||
# достижим, вымел бы в список мест ЗНАМЕНАТЕЛИ: «проверка sentences дала 90», «words дала 1154».
|
||||
# То есть починка одного типа сделала бы арм хуже, чем сломанный. Поэтому whitelist, а не эвристика.
|
||||
# ⚠⚠ ВТОРАЯ ПОЧИНКА (11.08, после того как 14 клеток A1B из 31 вернули ПУСТОТУ на потолке вывода,
|
||||
# $0.170 впустую). Первая редакция whitelist'а брала поля-СЧЁТЧИКИ, и два из них были ядовиты:
|
||||
#
|
||||
# * `palladius.nonconformant_bank` — это счёт строк САМОГО БАНКА, не прошедших палладиевскую
|
||||
# проверку (`battery.py:159` — `for d in bank_dst`). К переводу он не относится ВООБЩЕ: число
|
||||
# одинаково во всех 32 единицах, потому что банк один. Фиксеру говорилось «имена/термины
|
||||
# переданы мимо банка (8 шт.)», и он искал в тексте то, чего в тексте нет. Рассуждение
|
||||
# выросло вшестеро против A1 (40 694 знака против 7 400) и съело весь бюджет вывода.
|
||||
# * `ty_vy.mixed_in_unit` — адреса не имеет и сам докстринг проверки (`battery.py:365-370`)
|
||||
# называет её «сигналом к просмотру, а не счётом ошибок»: смешение между РАЗНЫМИ
|
||||
# собеседниками легитимно. Инструкцией фиксеру такое быть не может.
|
||||
#
|
||||
# НОРМА, ЗАВЕДЁННАЯ ЭТИМ: **флаг без адреса — не место.** Контракт арма — «черновик плюс СПИСОК
|
||||
# МЕСТ»; поле, которое не может назвать, ЧТО чинить, в список не идёт и остаётся описательным.
|
||||
# Поэтому ниже у каждого поля указано, откуда берётся адрес, и поля без адреса исключены.
|
||||
BATTERY_VIOLATIONS = {
|
||||
"palladius": ("nonconformant_bank",),
|
||||
"cjk_leak": ("over_probe_threshold", "over_prod_threshold"),
|
||||
"typography": ("violations", "ascii_quotes", "hyphen_as_dash"),
|
||||
"numbers": ("lost_n", "invented_n"),
|
||||
"ty_vy": ("mixed_in_unit",),
|
||||
"gender": ("mismatched",),
|
||||
# поле-признак поле-адрес (None = адрес находится по самому признаку)
|
||||
"palladius": (("nonconformant_text", "nonconformant_text_words"),),
|
||||
"cjk_leak": (("over_prod_threshold", None),),
|
||||
"typography": (("ascii_quotes", None), ("hyphen_as_dash", None)),
|
||||
"numbers": (("lost_n", "lost"), ("invented_n", "invented")),
|
||||
"gender": (("mismatched", "cases"),),
|
||||
}
|
||||
BATTERY_SAYS = {
|
||||
"palladius.nonconformant_bank": "имена/термины переданы мимо банка ({v} шт.)",
|
||||
"cjk_leak.over_probe_threshold": "в переводе остались иероглифы исходника",
|
||||
"cjk_leak.over_prod_threshold": "в переводе остались иероглифы исходника (сверх прод-порога)",
|
||||
"typography.violations": "нарушения типографики ({v} шт.)",
|
||||
"typography.ascii_quotes": "прямые кавычки вместо «ёлочек» ({v} шт.)",
|
||||
"typography.hyphen_as_dash": "дефис вместо тире ({v} шт.)",
|
||||
"numbers.lost_n": "числа исходника потеряны в переводе ({v} шт.)",
|
||||
"numbers.invented_n": "в переводе появились числа, которых нет в исходнике ({v} шт.)",
|
||||
"ty_vy.mixed_in_unit": "внутри единицы смешаны «ты» и «вы»",
|
||||
"gender.mismatched": "род персонажа расходится с карточкой ({v} шт.)",
|
||||
"palladius.nonconformant_text": "не-палладиевская транскрипция имени: {a}",
|
||||
"cjk_leak.over_prod_threshold": "в переводе остались иероглифы исходника: {a}",
|
||||
"typography.ascii_quotes": "прямые кавычки вместо «ёлочек», {v} шт.",
|
||||
"typography.hyphen_as_dash": "дефис вместо тире, {v} шт.",
|
||||
"numbers.lost_n": "величины исходника отсутствуют в переводе: {a}",
|
||||
"numbers.invented_n": "в переводе есть величины, которых нет в исходнике: {a}",
|
||||
"gender.mismatched": "род персонажа расходится с карточкой: {a}",
|
||||
}
|
||||
# ОПИСАТЕЛЬНЫЕ (печатаются как ось результата, фиксеру НЕ передаются — адреса нет):
|
||||
# ty_vy.mixed_in_unit · palladius.nonconformant_bank · typography.violations (агрегат)
|
||||
|
||||
|
||||
def battery_flags(u: dict, draft: str) -> list[str]:
|
||||
"""Нарушения батареи на тексте. Пустой список — законный ответ; ИСКЛЮЧЕНИЕ — не законный."""
|
||||
"""Нарушения батареи НА ТЕКСТЕ, каждое с адресом. Падение = дефект, НЕ глотаем."""
|
||||
import battery as B # noqa: PLC0415
|
||||
import re # noqa: PLC0415
|
||||
bank = BANK.PR.bank()
|
||||
unit = B.Unit(source=u["source"], draft=draft, final=draft,
|
||||
bank_dst={v["dst"] for v in bank.values()},
|
||||
term_pairs=[(t, v["dst"]) for t, v in bank.items() if u["source"].count(t)])
|
||||
r = B.run_unit(unit) # падение = дефект, НЕ глотаем
|
||||
r = B.run_unit(unit)
|
||||
out = []
|
||||
for check, fields in BATTERY_VIOLATIONS.items():
|
||||
val = r.get(check)
|
||||
if not isinstance(val, dict):
|
||||
continue
|
||||
for f in fields:
|
||||
v = val.get(f)
|
||||
if isinstance(v, (int, float, bool)) and v:
|
||||
out.append("БАТАРЕЯ: " + BATTERY_SAYS[f"{check}.{f}"].format(v=int(v)))
|
||||
for sig, addr_field in fields:
|
||||
v = val.get(sig)
|
||||
if not (isinstance(v, (int, float, bool)) and v):
|
||||
continue
|
||||
if addr_field:
|
||||
addr = val.get(addr_field) or []
|
||||
elif check == "cjk_leak":
|
||||
addr = sorted(set(re.findall(r"[一-鿿]", draft)))[:12]
|
||||
else:
|
||||
addr = []
|
||||
if addr_field and not addr: # признак есть, адреса нет — не место
|
||||
continue
|
||||
says = BATTERY_SAYS[f"{check}.{sig}"]
|
||||
out.append("БАТАРЕЯ: " + says.format(
|
||||
v=int(v), a="; ".join(f"«{x}»" for x in addr[:12])))
|
||||
return out
|
||||
|
||||
|
||||
|
|
@ -389,6 +415,17 @@ def cmd_selftest() -> int:
|
|||
ck("в места батареи не попали ЗНАМЕНАТЕЛИ (sentences/words/lines)",
|
||||
not any(w in f for f in bf for w in ("sentences", "words", "lines", "candidates")),
|
||||
"; ".join(bf[:2]))
|
||||
# ⚠ ФЛАГ БЕЗ АДРЕСА — НЕ МЕСТО. Норма заведена после того, как безадресный флаг (и притом
|
||||
# относящийся к БАНКУ, а не к тексту) отправил фиксера в неограниченный перебор: 14 клеток
|
||||
# A1B из 31 упёрлись в потолок вывода и вернули пустоту, $0.170 впустую. Гейт требует, чтобы
|
||||
# каждое место батареи несло либо цитату в «ёлочках», либо счёт находимого по признаку класса.
|
||||
allb = [f for x in us if base_draft(x["uid"]).strip()
|
||||
for f in battery_flags(x, base_draft(x["uid"]))]
|
||||
noaddr = [f for f in allb if "«" not in f and " шт." not in f]
|
||||
ck("каждое место батареи несёт АДРЕС (цитату либо находимый класс)",
|
||||
not noaddr, f"без адреса {len(noaddr)}: {noaddr[:2]}")
|
||||
ck("батарея не флагует свойства БАНКА вместо свойств текста",
|
||||
not any("мимо банка" in f for f in allb))
|
||||
# ⚠ A2: арм, которого не существовало — вызов падал TypeError, ветка отказа была недостижима.
|
||||
m2 = a2_msgs(u["source"])
|
||||
ck("A2 собирается (однопроходка уравненного мандата)", len(m2) >= 2)
|
||||
|
|
|
|||
|
|
@ -101,9 +101,19 @@ TAGS = {
|
|||
# Это ПЕРЕКЛАДКА внутри санкционированного пакета, пакетный потолок $6.00 не двигается; сумма
|
||||
# фазовых потолков 5.83 ≤ 6.00. Спрошено потому, что срабатывание гарда = вопрос владельцу по
|
||||
# заказу, а пак 23 потерял пункт CONFIRM/DENY ровно за то, что решил подобное сам.
|
||||
CEILINGS = {"ФД-A": 1.680, "ФД-B": 0.630, "ФД-C": 0.170, "ФД-D": 0.050,
|
||||
# ⚠ ПОТОЛОК $6.00 → $6.15 (санкция владельца 11.08, «поднимай»), ФД-A 1.680 → 1.950.
|
||||
# ПРИЧИНА — ОШИБКА СЕССИИ, И ЭТО ЗАПИСАНО ЗДЕСЬ, А НЕ СМЯГЧЕНО В ОТЧЁТЕ. Первая редакция списка
|
||||
# мест для арма A1B несла поле `palladius.nonconformant_bank` — счёт строк САМОГО БАНКА, не
|
||||
# прошедших палладиевскую проверку. К переводу оно не относится: число одинаково во всех единицах,
|
||||
# и фиксер искал в тексте то, чего в тексте нет. Рассуждение выросло вшестеро против A1 (40 694
|
||||
# знака против 7 400); 14 клеток из 31 упёрлись в потолок вывода и вернули ПУСТОТУ — $0.170
|
||||
# впустую. Ещё $0.186 стоили 16 завершившихся клеток, отправленных в карантин ради ОДНОРОДНОСТИ
|
||||
# арма: они построены на том же отравленном списке и одним армом с починенными быть не могут.
|
||||
# Без этой ошибки $6.00 хватало. Норма, заведённая ею: **флаг без адреса — не место**, и селфтест
|
||||
# `contour.py` теперь роняет харнесс, если безадресный флаг попадёт в список фиксеру.
|
||||
CEILINGS = {"ФД-A": 1.950, "ФД-B": 0.630, "ФД-C": 0.170, "ФД-D": 0.050,
|
||||
"ФД-E": 2.370, "ФД-F": 0.720, "ФД-G": 0.210}
|
||||
PACK_CEILING = 6.00
|
||||
PACK_CEILING = 6.15
|
||||
|
||||
M22.configure(ZONE=ZONE, OUT=OUT, TAGS=TAGS, CEILINGS=CEILINGS,
|
||||
PACK_CEILING=PACK_CEILING, GLOB_ALL="dv-*.json", ROSTER=ROSTER)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue