From db02b7ab64c69ad2478acedd0880344eb131d39a Mon Sep 17 00:00:00 2001 From: "Claude (backend session)" Date: Thu, 20 Aug 2026 20:38:56 +0300 Subject: [PATCH] Freeze the reading packet format: three judging axes and one chapter per packet --- eval/dovodka/rol.py | 37 ++++++++++++++++++++++++++++--------- eval/dovodka/runs.py | 15 ++++++++++++++- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/eval/dovodka/rol.py b/eval/dovodka/rol.py index ce1917ad..ed86744a 100644 --- a/eval/dovodka/rol.py +++ b/eval/dovodka/rol.py @@ -678,19 +678,26 @@ READ_PANEL = ("ZP", "RN", "Z0", "ZF") # склейка · новая рол READ_DIR = Path.home() / "books" / "chtenie-rol" READ_KEY = OUT / "blind-keys-rol" / "rol-KEY.json" READ_HEAD = """ -Ниже {n} перевода одного и того же отрывка, сделанных разными способами. Какой чем сделан — не +Ниже {n} переводов одного и того же отрывка, сделанных разными способами. Какой чем сделан — не сказано намеренно, метки перемешаны, расшифровка лежит отдельно и до твоего ответа не открывается. -Метки сквозные: `Т1` в первом отрывке и `Т1` во втором — один и тот же способ. -Твоя задача одна: **расставить варианты по тому, какой ты взял бы в книгу** — как русскую -художественную прозу, при условии что смысл исходника не переврали. Исходник приложен. +Исходник приложен. Оцени варианты по ТРЁМ вещам, в этом порядке важности: + +1. **СМЫСЛ** — не переврано ли то, что сказано в исходнике: участник действия, отрицание, число, + ранг, родство, кто кому что говорит; не пропало ли и не добавилось ли событие. +2. **БРАК** — явные дефекты русского текста: незаконченная фраза, сбитая атрибуция реплики, + рассогласование, оставшийся кусок исходного языка, глосса в скобках посреди прозы, имя, + меняющее форму или род. +3. **ХУДОЖЕСТВЕННОСТЬ** — читается ли это как русская проза или как перевод: живой ритм и голос + против кальки, канцелярита и подстрочника. ## Что записать — в файл `{answer}` 1. **ПОРЯДОК** — строкой: `Т3 > Т1 > Т2 > Т4`, от лучшего к худшему. Неразличимые соединяй `=`. -2. **По фразе на вариант**: почему. - -Если какой-то вариант покажется откровенно машинным — скажи прямо. + Это ответ на вопрос «какой ты взял бы в книгу»: смысл и брак — пороги, художественность решает + между теми, кто пороги прошёл. +2. **По каждому варианту** — по фразе на каждую из трёх осей, если есть что сказать. +3. Если вариант читается откровенно машинным — скажи прямо. --- """ @@ -706,7 +713,8 @@ def read_texts(p: str, uid: str) -> dict: return out -def emit_read(p: str, n_units: int = 3, panel: tuple = (), tag_: str = "") -> None: +def emit_read(p: str, n_units: int = 3, panel: tuple = (), tag_: str = "", + only_uid: str = "") -> None: """Пакет слепого чтения: ключ пишется ДО ответов, раскладка ОДНА на пару. ⚠ ПАНЕЛЬ И ИМЯ ПАКЕТА — ПАРАМЕТРЫ, И ЭТО НЕ УДОБСТВО. Слепое чтение стало ШТАТНЫМ прибором @@ -726,6 +734,8 @@ def emit_read(p: str, n_units: int = 3, panel: tuple = (), tag_: str = "") -> No tx = read_texts(p, u["uid"]) if all(tx[a].strip() for a in READ_PANEL): full.append((u["uid"], tx)) + if only_uid: + full = [x for x in full if x[0] == only_uid] full.sort(key=lambda x: -sum(len(x[1][a]) for a in READ_PANEL)) take = full[:n_units] if not take: @@ -795,8 +805,17 @@ if __name__ == "__main__": _pan = next((x.split("=", 1)[1].split(",") for x in a if x.startswith("--panel=")), []) _tag = next((x.split("=", 1)[1] for x in a if x.startswith("--tag=")), "") _n = next((int(x.split("=", 1)[1]) for x in a if x.startswith("--n=")), 3) + _each = "--each" in a for x in ([y for y in a[1:] if y in PAIRS] or list(PAIRS)): - emit_read(x, _n, tuple(_pan), _tag) + if not _each: + emit_read(x, _n, tuple(_pan), _tag) + continue + # ⚠ ОДНА ГЛАВА — ОДИН ПАКЕТ, решение владельца 20.08: главы большие, читателю с + # несколькими сразу тяжело, и он начинает экономить внимание на последних. + PAIRS[x]["wire"]() + for k, u in enumerate(chosen(x)[:_n], 1): + emit_read(x, 1, tuple(_pan), f"{_tag}-{u['uid'][:8]}" if _tag else u["uid"][:8], + only_uid=u["uid"]) elif a[0] == "--score-read": score_read() elif a[0] == "--coverage": diff --git a/eval/dovodka/runs.py b/eval/dovodka/runs.py index 28f6a68c..916fcd07 100644 --- a/eval/dovodka/runs.py +++ b/eval/dovodka/runs.py @@ -42,7 +42,20 @@ from pathlib import Path OUT = Path.home() / "books" / "dovodka" LEDGER = OUT / "agent-runs.json" -CAP = 80 +# ⚠ КАП ПОДНЯТ 80 → 100 ПО СЛОВУ ВЛАДЕЛЬЦА 15.08, дословно: «Почему оставшиеся? Почему на все их +# не хватит? Ты же можешь наспамить под 90 агентов (я видел и такое)». Заказ 10.08 ставил 80; +# владелец снял это ограничение прямой репликой, но в КОДЕ оно осталось и 16.08 упёрлось в +# середину регистрации судейских сессий захода Д17 — шесть сессий английской пары не записались. +# Сессии бесплатны (агенты, не API), поэтому кап здесь охраняет не деньги, а внимание: он ловит +# «сессий стало больше, чем кто-либо отслеживает». 100 покрывает заход с запасом. +# ⚠ 20.08: кап поднят 100 → 200 по слову владельца («Можно поднять, но я не припомню что б ставил +# тебе жёсткие ограничения»). Уточнение к истории, которое стоит записать: число 80 пришло из +# ЗАКАЗА (`POLYGON_EXP2223_REDO_SESSION_PROMPT.md:25`), владелец снял его 15.08, а число 100 сюда +# поставил Я САМ — то есть на 20.08 в кап упиралось МОЁ ограничение, а не его. Сессии бесплатны +# (агенты, не API), и кап охраняет не деньги, а внимание: он ловит «сессий стало больше, чем +# кто-либо отслеживает». 200 покрывает переход на слепое чтение как ШТАТНЫЙ прибор — там одна +# сессия на главу, то есть счёт идёт десятками, а не единицами. +CAP = 200 FAR_FUTURE = 1e18 LOCK_TRIES = 600 # ×0.1 с — минута ожидания живого замка